summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-28 16:09:26 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-28 19:51:56 +0200
commit45237bfd6ccbc07ddfd537ca5b968aae79589626 (patch)
treed2a15c5a4681254c45f750023044a4706be5466c
parentspec: Specify NTP support (diff)
downloadrtems-central-45237bfd6ccbc07ddfd537ca5b968aae79589626.tar.bz2
spec: Improve SMP-specific timecounter validation
-rw-r--r--spec/score/timecounter/val/get-smp.yml670
1 files changed, 603 insertions, 67 deletions
diff --git a/spec/score/timecounter/val/get-smp.yml b/spec/score/timecounter/val/get-smp.yml
index d3257d7a..dd09b357 100644
--- a/spec/score/timecounter/val/get-smp.yml
+++ b/spec/score/timecounter/val/get-smp.yml
@@ -9,54 +9,427 @@ test-actions:
action-code: |
Timecounter *tc;
rtems_id worker_id;
- Per_CPU_Control *cpu_self;
+ struct bintime bt;
+ sbintime_t sbt;
+ struct timespec ts;
+ struct timeval tv;
+ unsigned int i;
tc = &test_timecounter;
+ tc->base.tc_get_timecount = GetTimecount;
+ tc->base.tc_counter_mask = 0xffffffff;
+ tc->base.tc_frequency = 0x10000000;
+ tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install( &tc->base );
+
+ SetCounter( tc, tc->base.tc_frequency );
+ _Timecounter_Set_NTP_update_second( NtpUpdateSecond );
+ CallTimecounterTick();
+ _Timecounter_Set_NTP_update_second( NULL );
+
+ T_assert_not_null( tc->generation_0 );
+ T_assert_not_null( tc->generation_1 );
+
_SMP_barrier_Control_initialize( &tc->barrier );
_SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
_SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
worker_id = CreateTask( "WORK", PRIO_NORMAL );
SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
- StartTask( worker_id, Worker, tc );
+ StartTask( worker_id, SynchronousWorker, tc );
- tc->base.tc_get_timecount = GetTimecount;
- tc->base.tc_counter_mask = 0xffffffff;
- tc->base.tc_frequency = 0x10000000;
- tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
- rtems_timecounter_install( &tc->base );
-
- /* A */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ tc->base.tc_get_timecount = GetTimecountBarrier;
checks:
- brief: |
- Install a timecounter with a high quality level and normal frequency.
- Check that it was installed.
+ Call the ${/rtems/clock/if/get-realtime:/name} directive and let it
+ observe a generation number of zero as well as a generation number
+ change.
code: |
- /* B0 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ PrepareSynchronousWork( tc );
+ rtems_clock_get_realtime( &ts );
+ T_eq_i64( ts.tv_sec, 567993616 );
+ T_eq_long( ts.tv_nsec, 7 );
+ CleanupSynchronousWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-bintime:/name} directive and let
+ it observe a generation number of zero as well as a generation number
+ change.
+ code: |
+ PrepareSynchronousWork( tc );
+ rtems_clock_get_realtime_bintime( &bt );
+ T_eq_i64( bt.sec, 567993616 );
+ T_eq_u64( bt.frac, 137438953472 );
+ CleanupSynchronousWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-timeval:/name} directive and let
+ it observe a generation number of zero as well as a generation number
+ change.
+ code: |
+ PrepareSynchronousWork( tc );
+ rtems_clock_get_realtime_timeval( &tv );
+ T_eq_i64( tv.tv_sec, 567993616 );
+ T_eq_long( tv.tv_usec, 0 );
+ CleanupSynchronousWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic:/name} directive and let it
+ observe a generation number of zero as well as a generation number
+ change.
+ code: |
+ PrepareSynchronousWork( tc );
+ rtems_clock_get_monotonic( &ts );
+ T_eq_i64( ts.tv_sec, 17 );
+ T_eq_long( ts.tv_nsec, 7 );
+ CleanupSynchronousWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-bintime:/name} directive and let
+ it observe a generation number of zero as well as a generation number
+ change.
+ code: |
+ PrepareSynchronousWork( tc );
+ rtems_clock_get_monotonic_bintime( &bt );
+ T_eq_i64( bt.sec, 17 );
+ T_eq_u64( bt.frac, 137438953472 );
+ CleanupSynchronousWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-sbintime:/name} directive and let
+ it observe a generation number of zero as well as a generation number
+ change.
+ code: |
+ PrepareSynchronousWork( tc );
+ sbt = rtems_clock_get_monotonic_sbintime();
+ T_eq_i64( sbt, 73014444064 );
+ CleanupSynchronousWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-timeval:/name} directive and let
+ it observe a generation number of zero as well as a generation number
+ change.
+ code: |
+ PrepareSynchronousWork( tc );
+ rtems_clock_get_monotonic_timeval( &tv );
+ T_eq_i64( tv.tv_sec, 17 );
+ T_eq_long( tv.tv_usec, 0 );
+ CleanupSynchronousWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic
+ - brief: |
+ Delete the synchronous worker task. Reinitialize the barrier and barrier
+ states. Start the zero worker task.
+ code: |
+ tc->base.tc_get_timecount = GetTimecount;
+ DeleteTask( worker_id );
- /* B1 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ _SMP_barrier_Control_initialize( &tc->barrier );
+ _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
+ _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
- cpu_self = _Thread_Dispatch_disable();
- tc->delay = false;
- rtems_timecounter_tick();
- tc->delay = true;
- rtems_timecounter_tick();
- _Thread_Dispatch_enable( cpu_self );
+ worker_id = CreateTask( "WORK", PRIO_NORMAL );
+ SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
+ StartTask( worker_id, ZeroWorker, tc );
+ links: []
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-coarse:/name} directive and try
+ to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_realtime_coarse( &ts );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-coarse-bintime:/name} directive
+ and try to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_realtime_coarse_bintime( &bt );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-coarse-timeval:/name} directive
+ and try to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_realtime_coarse_timeval( &tv );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-coarse:/name} directive and try
+ to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_monotonic_coarse( &ts );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-coarse-bintime:/name} directive
+ and try to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_monotonic_coarse_bintime( &bt );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-coarse-timeval:/name} directive
+ and try to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_monotonic_coarse_timeval( &tv );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-boot-time:/name} directive and try
+ to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_boot_time( &ts );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-boot-time
+ - brief: |
+ Call the ${/rtems/clock/if/get-boot-time-bintime:/name} directive
+ and try to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_boot_time_bintime( &bt );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-boot-time
+ - brief: |
+ Call the ${/rtems/clock/if/get-boot-time-timeval:/name} directive
+ and try to let it observe a generation number of zero.
+ code: |
+ PrepareZeroWork( tc );
+ rtems_clock_get_boot_time_timeval( &tv );
+ CleanupZeroWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-boot-time
+ - brief: |
+ Delete the zero worker task. Reinitialize the barrier and barrier
+ states. Start the change worker task.
+ code: |
+ DeleteTask( worker_id );
+
+ _SMP_barrier_Control_initialize( &tc->barrier );
+ _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
+ _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
+
+ worker_id = CreateTask( "WORK", PRIO_NORMAL );
+ SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
+ StartTask( worker_id, ChangeWorker, tc );
+ links: []
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-coarse:/name} directive and try
+ to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
- /* B4 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_realtime_coarse( &ts );
+ }
- /* B5 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-coarse-bintime:/name} directive
+ and try to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
- tc->base.tc_get_timecount = GetTimecountDummy;
- DeleteTask( worker_id );
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_realtime_coarse_bintime( &bt );
+ }
+
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-realtime-coarse-timeval:/name} directive
+ and try to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
+
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_realtime_coarse_timeval( &tv );
+ }
+
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-realtime-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-coarse:/name} directive and try
+ to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
+
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_monotonic_coarse( &ts );
+ }
+
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-coarse-bintime:/name} directive
+ and try to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
+
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_monotonic_coarse_bintime( &bt );
+ }
+
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-monotonic-coarse-timeval:/name} directive
+ and try to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
+
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_monotonic_coarse_timeval( &tv );
+ }
+
+ CleanupChangeWork( tc );
links:
- role: validation
- uid: ../req/install-quality
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-monotonic-coarse
+ - brief: |
+ Call the ${/rtems/clock/if/get-boot-time:/name} directive and try
+ to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
+
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_boot_time( &ts );
+ }
+
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-boot-time
+ - brief: |
+ Call the ${/rtems/clock/if/get-boot-time-bintime:/name} directive
+ and try to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
+
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_boot_time_bintime( &bt );
+ }
+
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-boot-time
+ - brief: |
+ Call the ${/rtems/clock/if/get-boot-time-timeval:/name} directive
+ and try to let it observe a changing generation number.
+ code: |
+ PrepareChangeWork( tc );
+
+ for ( i = 0; i < 100; ++i ) {
+ rtems_clock_get_boot_time_timeval( &tv );
+ }
+
+ CleanupChangeWork( tc );
+ links:
+ - role: validation
+ uid: ../req/get-non-blocking
+ - role: validation
+ uid: /rtems/clock/req/get-boot-time
+ - brief: |
+ Delete the change worker task.
+ code: |
+ DeleteTask( worker_id );
+ links: []
links: []
test-brief: |
Tests directives to get a time value.
@@ -66,6 +439,7 @@ test-description: null
test-header: null
test-includes:
- rtems.h
+- rtems/counter.h
- rtems/timecounter.h
- rtems/score/threaddispatch.h
- rtems/score/smpbarrier.h
@@ -76,8 +450,9 @@ test-stop: null
test-support: |
typedef struct {
struct timecounter base;
- bool delay;
- uint32_t counter;
+ Atomic_Ulong counter;
+ Atomic_Uint *generation_0;
+ Atomic_Uint *generation_1;
SMP_barrier_Control barrier;
SMP_barrier_State barrier_state[ 2 ];
} Timecounter;
@@ -90,71 +465,232 @@ test-support: |
tc = (Timecounter *) base;
- if ( rtems_scheduler_get_processor() == 0 ) {
- if ( !tc->delay ) {
- return 0;
- }
+ return (uint32_t) _Atomic_Fetch_add_ulong(
+ &tc->counter,
+ 1,
+ ATOMIC_ORDER_RELAXED
+ );
+ }
- /* B2 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ static uint32_t GetTimecountBarrier( struct timecounter *base )
+ {
+ Timecounter *tc;
- /* B3 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ tc = (Timecounter *) base;
- return 0;
- }
+ /* C0, C1, C2 */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+ /* D0, D1, D2 */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+ return GetTimecount( &tc->base );
+ }
+
+ static uint32_t GetCounter( const Timecounter *tc )
+ {
+ return (uint32_t) _Atomic_Load_ulong(
+ &tc->counter,
+ ATOMIC_ORDER_RELAXED
+ );
+ }
+
+ static void SetCounter( Timecounter *tc, uint32_t counter )
+ {
+ _Atomic_Store_ulong(
+ &tc->counter,
+ counter,
+ ATOMIC_ORDER_RELAXED
+ );
+ }
+
+ static void CallTimecounterTick( void )
+ {
+ Per_CPU_Control *cpu_self;
- if ( tc->counter == 0 ) {
- /* Do nothing */
- } else if ( tc->counter == 1 ) {
- tc->counter = 2;
+ cpu_self = _Thread_Dispatch_disable();
+ rtems_timecounter_tick();
+ _Thread_Dispatch_enable( cpu_self );
+ }
+
+ static void SetGeneration( Timecounter *tc, unsigned int generation )
+ {
+ _Atomic_Store_uint( tc->generation_0, generation, ATOMIC_ORDER_RELAXED );
+ _Atomic_Store_uint( tc->generation_1, generation, ATOMIC_ORDER_RELAXED );
+ }
+
+ static void PrepareSynchronousWork( Timecounter *tc )
+ {
+ /* A */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+ SetCounter( tc, 0 );
+
+ /* B */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ }
- /* B1 */
+ static void CleanupSynchronousWork( Timecounter *tc )
+ {
+ /* E */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+ T_eq_u32( GetCounter( tc ), 3 );
+ }
+
+ static void SynchronousWorker( rtems_task_argument arg )
+ {
+ Timecounter *tc;
+
+ tc = (Timecounter *) arg;
+
+ while ( true ) {
+ /* A */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ SetGeneration( tc, 0 );
+
+ /* B */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ /* C0 */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ SetGeneration( tc, 1 );
+
+ /* D0 */
_SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
- /* B2 */
+ /* C1 */
_SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
- } else if ( tc->counter == 2 ) {
- tc->counter = 3;
- /* B3 */
+ SetGeneration( tc, 2 );
+
+ /* D1 */
_SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
- /* B4 */
+ /* C2 */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ /* D2 */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ /* E */
_SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
}
+ }
- return 0;
+ static void PrepareZeroWork( Timecounter *tc )
+ {
+ /* F */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+ SetCounter( tc, 0 );
+
+ /* G */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
}
- static uint32_t GetTimecountDummy( struct timecounter *base )
+ static void CleanupZeroWork( Timecounter *tc )
{
- (void) base;
+ /* H */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
- return 0;
+ T_eq_u32( GetCounter( tc ), 0 );
}
- static void Worker( rtems_task_argument arg )
+ static void ZeroWorker( rtems_task_argument arg )
{
- Timecounter *tc;
- struct bintime bt;
+ Timecounter *tc;
tc = (Timecounter *) arg;
- /* A */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+ while ( true ) {
+ /* F */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ SetGeneration( tc, 0 );
- tc->counter = 1;
+ /* G */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ rtems_counter_delay_nanoseconds( 10000000 );
+ SetGeneration( tc, 1 );
+
+ /* H */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+ }
+ }
+
+ static void PrepareChangeWork( Timecounter *tc )
+ {
+ /* F */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+ SetCounter( tc, 0 );
+
+ /* G */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+ }
+
+ static void CleanupChangeWork( Timecounter *tc )
+ {
+ /* H */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+ T_eq_u32( GetCounter( tc ), 0 );
+ }
- /* B0 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+ static void ChangeWorker( rtems_task_argument arg )
+ {
+ Timecounter *tc;
- rtems_clock_get_realtime_bintime( &bt );
+ tc = (Timecounter *) arg;
- /* B5 */
- _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+ while ( true ) {
+ unsigned int i;
- ReceiveAnyEvents();
+ /* F */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ /* G */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+ for ( i = 1; i < 1000; ++i ) {
+ SetGeneration( tc, i );
+ }
+
+ /* H */
+ _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+ }
+ }
+
+ /* This definition must be identical to the one in kern_tc.c */
+ struct timehands {
+ struct timecounter *th_counter;
+ int64_t th_adjustment;
+ uint64_t th_scale;
+ uint32_t th_large_delta;
+ uint32_t th_offset_count;
+ struct bintime th_offset;
+ struct bintime th_bintime;
+ struct timeval th_microtime;
+ struct timespec th_nanotime;
+ struct bintime th_boottime;
+ Atomic_Uint th_generation;
+ struct timehands *th_next;
+ };
+
+ static void NtpUpdateSecond( int64_t *adjustment, time_t *newsec )
+ {
+ Timecounter *tc;
+ struct timehands *th;
+
+ tc = &test_timecounter;
+ th = RTEMS_CONTAINER_OF( adjustment, struct timehands, th_adjustment );
+ T_assert_eq_ptr( th, th->th_next->th_next );
+ tc->generation_0 = &th->th_generation;
+ tc->generation_1 = &th->th_next->th_generation;
}
test-target: testsuites/validation/tc-timecounter-get-smp.c
test-teardown: null