Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:53

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup ScoreTimecounterValGetSmp
0007  */
0008 
0009 /*
0010  * Copyright (C) 2021 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 /*
0035  * This file is part of the RTEMS quality process and was automatically
0036  * generated.  If you find something that needs to be fixed or
0037  * worded better please post a report or patch to an RTEMS mailing list
0038  * or raise a bug report:
0039  *
0040  * https://www.rtems.org/bugs.html
0041  *
0042  * For information on updating and regenerating please refer to the How-To
0043  * section in the Software Requirements Engineering chapter of the
0044  * RTEMS Software Engineering manual.  The manual is provided as a part of
0045  * a release.  For development sources please refer to the online
0046  * documentation at:
0047  *
0048  * https://docs.rtems.org
0049  */
0050 
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054 
0055 #include <rtems.h>
0056 #include <rtems/counter.h>
0057 #include <rtems/timecounter.h>
0058 #include <rtems/score/smpbarrier.h>
0059 #include <rtems/score/threaddispatch.h>
0060 
0061 #include "tx-support.h"
0062 
0063 #include <rtems/test.h>
0064 
0065 /**
0066  * @defgroup ScoreTimecounterValGetSmp spec:/score/timecounter/val/get-smp
0067  *
0068  * @ingroup TestsuitesValidationTimecounterSmp0
0069  *
0070  * @brief Tests directives to get a time value.
0071  *
0072  * This test case performs the following actions:
0073  *
0074  * - Install timecounter of different quality levels and frequencies.
0075  *
0076  *   - Call the rtems_clock_get_realtime() directive and let it observe a
0077  *     generation number of zero as well as a generation number change.
0078  *
0079  *   - Call the rtems_clock_get_realtime_bintime() directive and let it observe
0080  *     a generation number of zero as well as a generation number change.
0081  *
0082  *   - Call the rtems_clock_get_realtime_timeval() directive and let it observe
0083  *     a generation number of zero as well as a generation number change.
0084  *
0085  *   - Call the rtems_clock_get_monotonic() directive and let it observe a
0086  *     generation number of zero as well as a generation number change.
0087  *
0088  *   - Call the rtems_clock_get_monotonic_bintime() directive and let it
0089  *     observe a generation number of zero as well as a generation number
0090  *     change.
0091  *
0092  *   - Call the rtems_clock_get_monotonic_sbintime() directive and let it
0093  *     observe a generation number of zero as well as a generation number
0094  *     change.
0095  *
0096  *   - Call the rtems_clock_get_monotonic_timeval() directive and let it
0097  *     observe a generation number of zero as well as a generation number
0098  *     change.
0099  *
0100  *   - Delete the synchronous worker task.  Reinitialize the barrier and
0101  *     barrier states.  Start the zero worker task.
0102  *
0103  *   - Call the rtems_clock_get_realtime_coarse() directive and try to let it
0104  *     observe a generation number of zero.
0105  *
0106  *   - Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
0107  *     let it observe a generation number of zero.
0108  *
0109  *   - Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
0110  *     let it observe a generation number of zero.
0111  *
0112  *   - Call the rtems_clock_get_monotonic_coarse() directive and try to let it
0113  *     observe a generation number of zero.
0114  *
0115  *   - Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
0116  *     let it observe a generation number of zero.
0117  *
0118  *   - Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
0119  *     let it observe a generation number of zero.
0120  *
0121  *   - Call the rtems_clock_get_boot_time() directive and try to let it observe
0122  *     a generation number of zero.
0123  *
0124  *   - Call the rtems_clock_get_boot_time_bintime() directive and try to let it
0125  *     observe a generation number of zero.
0126  *
0127  *   - Call the rtems_clock_get_boot_time_timeval() directive and try to let it
0128  *     observe a generation number of zero.
0129  *
0130  *   - Delete the zero worker task.  Reinitialize the barrier and barrier
0131  *     states.  Start the change worker task.
0132  *
0133  *   - Call the rtems_clock_get_realtime_coarse() directive and try to let it
0134  *     observe a changing generation number.
0135  *
0136  *   - Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
0137  *     let it observe a changing generation number.
0138  *
0139  *   - Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
0140  *     let it observe a changing generation number.
0141  *
0142  *   - Call the rtems_clock_get_monotonic_coarse() directive and try to let it
0143  *     observe a changing generation number.
0144  *
0145  *   - Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
0146  *     let it observe a changing generation number.
0147  *
0148  *   - Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
0149  *     let it observe a changing generation number.
0150  *
0151  *   - Call the rtems_clock_get_boot_time() directive and try to let it observe
0152  *     a changing generation number.
0153  *
0154  *   - Call the rtems_clock_get_boot_time_bintime() directive and try to let it
0155  *     observe a changing generation number.
0156  *
0157  *   - Call the rtems_clock_get_boot_time_timeval() directive and try to let it
0158  *     observe a changing generation number.
0159  *
0160  *   - Delete the change worker task.
0161  *
0162  * @{
0163  */
0164 
0165 typedef struct {
0166   struct timecounter  base;
0167   Atomic_Ulong        counter;
0168   Atomic_Uint        *generation_0;
0169   Atomic_Uint        *generation_1;
0170   SMP_barrier_Control barrier;
0171   SMP_barrier_State   barrier_state[ 2 ];
0172 } Timecounter;
0173 
0174 static Timecounter test_timecounter;
0175 
0176 static uint32_t GetTimecount( struct timecounter *base )
0177 {
0178   Timecounter *tc;
0179 
0180   tc = (Timecounter *) base;
0181 
0182   return (uint32_t) _Atomic_Fetch_add_ulong(
0183     &tc->counter,
0184     1,
0185     ATOMIC_ORDER_RELAXED
0186   );
0187 }
0188 
0189 static uint32_t GetTimecountBarrier( struct timecounter *base )
0190 {
0191   Timecounter *tc;
0192 
0193   tc = (Timecounter *) base;
0194 
0195   /* C0, C1, C2 */
0196   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0197 
0198   /* D0, D1, D2 */
0199   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0200 
0201   return GetTimecount( &tc->base );
0202 }
0203 
0204 static uint32_t GetCounter( const Timecounter *tc )
0205 {
0206   return (uint32_t) _Atomic_Load_ulong(
0207     &tc->counter,
0208     ATOMIC_ORDER_RELAXED
0209   );
0210 }
0211 
0212 static void SetCounter( Timecounter *tc, uint32_t counter )
0213 {
0214   _Atomic_Store_ulong(
0215     &tc->counter,
0216     counter,
0217     ATOMIC_ORDER_RELAXED
0218   );
0219 }
0220 
0221 static void CallTimecounterTick( void )
0222 {
0223   Per_CPU_Control *cpu_self;
0224 
0225   cpu_self = _Thread_Dispatch_disable();
0226   rtems_timecounter_tick();
0227   _Thread_Dispatch_enable( cpu_self );
0228 }
0229 
0230 static void SetGeneration( Timecounter *tc, unsigned int generation )
0231 {
0232   _Atomic_Store_uint( tc->generation_0, generation, ATOMIC_ORDER_RELAXED );
0233   _Atomic_Store_uint( tc->generation_1, generation, ATOMIC_ORDER_RELAXED );
0234 }
0235 
0236 static void PrepareSynchronousWork( Timecounter *tc )
0237 {
0238   /* A */
0239   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0240 
0241   SetCounter( tc, 0 );
0242 
0243   /* B */
0244   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0245 }
0246 
0247 static void CleanupSynchronousWork( Timecounter *tc )
0248 {
0249   /* E */
0250   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0251 
0252   T_eq_u32( GetCounter( tc ), 3 );
0253 }
0254 
0255 static void SynchronousWorker( rtems_task_argument arg )
0256 {
0257   Timecounter *tc;
0258 
0259   tc = (Timecounter *) arg;
0260 
0261   while ( true ) {
0262     /* A */
0263     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0264 
0265     SetGeneration( tc, 0 );
0266 
0267     /* B */
0268     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0269 
0270     /* C0 */
0271     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0272 
0273     SetGeneration( tc, 1 );
0274 
0275     /* D0 */
0276     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0277 
0278     /* C1 */
0279     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0280 
0281     SetGeneration( tc, 2 );
0282 
0283     /* D1 */
0284     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0285 
0286     /* C2 */
0287     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0288 
0289     /* D2 */
0290     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0291 
0292     /* E */
0293     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0294   }
0295 }
0296 
0297 static void PrepareZeroWork( Timecounter *tc )
0298 {
0299   /* F */
0300   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0301 
0302   SetCounter( tc, 0 );
0303 
0304   /* G */
0305   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0306 }
0307 
0308 static void CleanupZeroWork( Timecounter *tc )
0309 {
0310   /* H */
0311   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0312 
0313   T_eq_u32( GetCounter( tc ), 0 );
0314 }
0315 
0316 static void ZeroWorker( rtems_task_argument arg )
0317 {
0318   Timecounter *tc;
0319 
0320   tc = (Timecounter *) arg;
0321 
0322   while ( true ) {
0323     /* F */
0324     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0325 
0326     SetGeneration( tc, 0 );
0327 
0328     /* G */
0329     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0330 
0331     rtems_counter_delay_nanoseconds( 10000000 );
0332     SetGeneration( tc, 1 );
0333 
0334     /* H */
0335     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0336   }
0337 }
0338 
0339 static void PrepareChangeWork( Timecounter *tc )
0340 {
0341   /* F */
0342   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0343 
0344   SetCounter( tc, 0 );
0345 
0346   /* G */
0347   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0348 }
0349 
0350 static void CleanupChangeWork( Timecounter *tc )
0351 {
0352   /* H */
0353   _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
0354 
0355   T_eq_u32( GetCounter( tc ), 0 );
0356 }
0357 
0358 static void ChangeWorker( rtems_task_argument arg )
0359 {
0360   Timecounter *tc;
0361 
0362   tc = (Timecounter *) arg;
0363 
0364   while ( true ) {
0365     unsigned int i;
0366 
0367     /* F */
0368     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0369 
0370     /* G */
0371     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0372 
0373     for ( i = 1; i < 1000; ++i ) {
0374       SetGeneration( tc, i );
0375     }
0376 
0377     /* H */
0378     _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
0379   }
0380 }
0381 
0382 /* This definition must be identical to the one in kern_tc.c */
0383 struct timehands {
0384   struct timecounter *th_counter;
0385   int64_t             th_adjustment;
0386   uint64_t            th_scale;
0387   uint32_t            th_large_delta;
0388   uint32_t            th_offset_count;
0389   struct bintime      th_offset;
0390   struct bintime      th_bintime;
0391   struct timeval      th_microtime;
0392   struct timespec     th_nanotime;
0393   struct bintime      th_boottime;
0394   Atomic_Uint         th_generation;
0395   struct timehands   *th_next;
0396 };
0397 
0398 static void NtpUpdateSecond( int64_t *adjustment, time_t *newsec )
0399 {
0400   Timecounter      *tc;
0401   struct timehands *th;
0402 
0403   tc = &test_timecounter;
0404   th = RTEMS_CONTAINER_OF( adjustment, struct timehands, th_adjustment );
0405   T_assert_eq_ptr( th, th->th_next->th_next );
0406   tc->generation_0 = &th->th_generation;
0407   tc->generation_1 = &th->th_next->th_generation;
0408 }
0409 
0410 /**
0411  * @brief Install timecounter of different quality levels and frequencies.
0412  */
0413 static void ScoreTimecounterValGetSmp_Action_0( void )
0414 {
0415   Timecounter     *tc;
0416   rtems_id         worker_id;
0417   struct bintime   bt;
0418   sbintime_t       sbt;
0419   struct timespec  ts;
0420   struct timeval   tv;
0421   unsigned int     i;
0422 
0423   tc = &test_timecounter;
0424   tc->base.tc_get_timecount = GetTimecount;
0425   tc->base.tc_counter_mask = 0xffffffff;
0426   tc->base.tc_frequency = 0x10000000;
0427   tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0428   rtems_timecounter_install( &tc->base );
0429 
0430   SetCounter( tc, tc->base.tc_frequency );
0431   _Timecounter_Set_NTP_update_second( NtpUpdateSecond );
0432   CallTimecounterTick();
0433   _Timecounter_Set_NTP_update_second( NULL );
0434 
0435   T_assert_not_null( tc->generation_0 );
0436   T_assert_not_null( tc->generation_1 );
0437 
0438   _SMP_barrier_Control_initialize( &tc->barrier );
0439   _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
0440   _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
0441 
0442   worker_id = CreateTask( "WORK", PRIO_NORMAL );
0443   SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0444   StartTask( worker_id, SynchronousWorker, tc );
0445 
0446   tc->base.tc_get_timecount = GetTimecountBarrier;
0447 
0448   /*
0449    * Call the rtems_clock_get_realtime() directive and let it observe a
0450    * generation number of zero as well as a generation number change.
0451    */
0452   PrepareSynchronousWork( tc );
0453   rtems_clock_get_realtime( &ts );
0454   T_eq_i64( ts.tv_sec, 567993616 );
0455   T_eq_long( ts.tv_nsec, 7 );
0456   CleanupSynchronousWork( tc );
0457 
0458   /*
0459    * Call the rtems_clock_get_realtime_bintime() directive and let it observe a
0460    * generation number of zero as well as a generation number change.
0461    */
0462   PrepareSynchronousWork( tc );
0463   rtems_clock_get_realtime_bintime( &bt );
0464   T_eq_i64( bt.sec, 567993616 );
0465   T_eq_u64( bt.frac, 137438953472 );
0466   CleanupSynchronousWork( tc );
0467 
0468   /*
0469    * Call the rtems_clock_get_realtime_timeval() directive and let it observe a
0470    * generation number of zero as well as a generation number change.
0471    */
0472   PrepareSynchronousWork( tc );
0473   rtems_clock_get_realtime_timeval( &tv );
0474   T_eq_i64( tv.tv_sec, 567993616 );
0475   T_eq_long( tv.tv_usec, 0 );
0476   CleanupSynchronousWork( tc );
0477 
0478   /*
0479    * Call the rtems_clock_get_monotonic() directive and let it observe a
0480    * generation number of zero as well as a generation number change.
0481    */
0482   PrepareSynchronousWork( tc );
0483   rtems_clock_get_monotonic( &ts );
0484   T_eq_i64( ts.tv_sec, 17 );
0485   T_eq_long( ts.tv_nsec, 7 );
0486   CleanupSynchronousWork( tc );
0487 
0488   /*
0489    * Call the rtems_clock_get_monotonic_bintime() directive and let it observe
0490    * a generation number of zero as well as a generation number change.
0491    */
0492   PrepareSynchronousWork( tc );
0493   rtems_clock_get_monotonic_bintime( &bt );
0494   T_eq_i64( bt.sec, 17 );
0495   T_eq_u64( bt.frac, 137438953472 );
0496   CleanupSynchronousWork( tc );
0497 
0498   /*
0499    * Call the rtems_clock_get_monotonic_sbintime() directive and let it observe
0500    * a generation number of zero as well as a generation number change.
0501    */
0502   PrepareSynchronousWork( tc );
0503   sbt = rtems_clock_get_monotonic_sbintime();
0504   T_eq_i64( sbt, 73014444064 );
0505   CleanupSynchronousWork( tc );
0506 
0507   /*
0508    * Call the rtems_clock_get_monotonic_timeval() directive and let it observe
0509    * a generation number of zero as well as a generation number change.
0510    */
0511   PrepareSynchronousWork( tc );
0512   rtems_clock_get_monotonic_timeval( &tv );
0513   T_eq_i64( tv.tv_sec, 17 );
0514   T_eq_long( tv.tv_usec, 0 );
0515   CleanupSynchronousWork( tc );
0516 
0517   /*
0518    * Delete the synchronous worker task.  Reinitialize the barrier and barrier
0519    * states.  Start the zero worker task.
0520    */
0521   tc->base.tc_get_timecount = GetTimecount;
0522   DeleteTask( worker_id );
0523 
0524   _SMP_barrier_Control_initialize( &tc->barrier );
0525   _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
0526   _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
0527 
0528   worker_id = CreateTask( "WORK", PRIO_NORMAL );
0529   SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0530   StartTask( worker_id, ZeroWorker, tc );
0531 
0532   /*
0533    * Call the rtems_clock_get_realtime_coarse() directive and try to let it
0534    * observe a generation number of zero.
0535    */
0536   PrepareZeroWork( tc );
0537   rtems_clock_get_realtime_coarse( &ts );
0538   CleanupZeroWork( tc );
0539 
0540   /*
0541    * Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
0542    * let it observe a generation number of zero.
0543    */
0544   PrepareZeroWork( tc );
0545   rtems_clock_get_realtime_coarse_bintime( &bt );
0546   CleanupZeroWork( tc );
0547 
0548   /*
0549    * Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
0550    * let it observe a generation number of zero.
0551    */
0552   PrepareZeroWork( tc );
0553   rtems_clock_get_realtime_coarse_timeval( &tv );
0554   CleanupZeroWork( tc );
0555 
0556   /*
0557    * Call the rtems_clock_get_monotonic_coarse() directive and try to let it
0558    * observe a generation number of zero.
0559    */
0560   PrepareZeroWork( tc );
0561   rtems_clock_get_monotonic_coarse( &ts );
0562   CleanupZeroWork( tc );
0563 
0564   /*
0565    * Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
0566    * let it observe a generation number of zero.
0567    */
0568   PrepareZeroWork( tc );
0569   rtems_clock_get_monotonic_coarse_bintime( &bt );
0570   CleanupZeroWork( tc );
0571 
0572   /*
0573    * Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
0574    * let it observe a generation number of zero.
0575    */
0576   PrepareZeroWork( tc );
0577   rtems_clock_get_monotonic_coarse_timeval( &tv );
0578   CleanupZeroWork( tc );
0579 
0580   /*
0581    * Call the rtems_clock_get_boot_time() directive and try to let it observe a
0582    * generation number of zero.
0583    */
0584   PrepareZeroWork( tc );
0585   rtems_clock_get_boot_time( &ts );
0586   CleanupZeroWork( tc );
0587 
0588   /*
0589    * Call the rtems_clock_get_boot_time_bintime() directive and try to let it
0590    * observe a generation number of zero.
0591    */
0592   PrepareZeroWork( tc );
0593   rtems_clock_get_boot_time_bintime( &bt );
0594   CleanupZeroWork( tc );
0595 
0596   /*
0597    * Call the rtems_clock_get_boot_time_timeval() directive and try to let it
0598    * observe a generation number of zero.
0599    */
0600   PrepareZeroWork( tc );
0601   rtems_clock_get_boot_time_timeval( &tv );
0602   CleanupZeroWork( tc );
0603 
0604   /*
0605    * Delete the zero worker task.  Reinitialize the barrier and barrier states.
0606    * Start the change worker task.
0607    */
0608   DeleteTask( worker_id );
0609 
0610   _SMP_barrier_Control_initialize( &tc->barrier );
0611   _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
0612   _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
0613 
0614   worker_id = CreateTask( "WORK", PRIO_NORMAL );
0615   SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
0616   StartTask( worker_id, ChangeWorker, tc );
0617 
0618   /*
0619    * Call the rtems_clock_get_realtime_coarse() directive and try to let it
0620    * observe a changing generation number.
0621    */
0622   PrepareChangeWork( tc );
0623 
0624   for ( i = 0; i < 100; ++i ) {
0625     rtems_clock_get_realtime_coarse( &ts );
0626   }
0627 
0628   CleanupChangeWork( tc );
0629 
0630   /*
0631    * Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
0632    * let it observe a changing generation number.
0633    */
0634   PrepareChangeWork( tc );
0635 
0636   for ( i = 0; i < 100; ++i ) {
0637     rtems_clock_get_realtime_coarse_bintime( &bt );
0638   }
0639 
0640   CleanupChangeWork( tc );
0641 
0642   /*
0643    * Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
0644    * let it observe a changing generation number.
0645    */
0646   PrepareChangeWork( tc );
0647 
0648   for ( i = 0; i < 100; ++i ) {
0649     rtems_clock_get_realtime_coarse_timeval( &tv );
0650   }
0651 
0652   CleanupChangeWork( tc );
0653 
0654   /*
0655    * Call the rtems_clock_get_monotonic_coarse() directive and try to let it
0656    * observe a changing generation number.
0657    */
0658   PrepareChangeWork( tc );
0659 
0660   for ( i = 0; i < 100; ++i ) {
0661     rtems_clock_get_monotonic_coarse( &ts );
0662   }
0663 
0664   CleanupChangeWork( tc );
0665 
0666   /*
0667    * Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
0668    * let it observe a changing generation number.
0669    */
0670   PrepareChangeWork( tc );
0671 
0672   for ( i = 0; i < 100; ++i ) {
0673     rtems_clock_get_monotonic_coarse_bintime( &bt );
0674   }
0675 
0676   CleanupChangeWork( tc );
0677 
0678   /*
0679    * Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
0680    * let it observe a changing generation number.
0681    */
0682   PrepareChangeWork( tc );
0683 
0684   for ( i = 0; i < 100; ++i ) {
0685     rtems_clock_get_monotonic_coarse_timeval( &tv );
0686   }
0687 
0688   CleanupChangeWork( tc );
0689 
0690   /*
0691    * Call the rtems_clock_get_boot_time() directive and try to let it observe a
0692    * changing generation number.
0693    */
0694   PrepareChangeWork( tc );
0695 
0696   for ( i = 0; i < 100; ++i ) {
0697     rtems_clock_get_boot_time( &ts );
0698   }
0699 
0700   CleanupChangeWork( tc );
0701 
0702   /*
0703    * Call the rtems_clock_get_boot_time_bintime() directive and try to let it
0704    * observe a changing generation number.
0705    */
0706   PrepareChangeWork( tc );
0707 
0708   for ( i = 0; i < 100; ++i ) {
0709     rtems_clock_get_boot_time_bintime( &bt );
0710   }
0711 
0712   CleanupChangeWork( tc );
0713 
0714   /*
0715    * Call the rtems_clock_get_boot_time_timeval() directive and try to let it
0716    * observe a changing generation number.
0717    */
0718   PrepareChangeWork( tc );
0719 
0720   for ( i = 0; i < 100; ++i ) {
0721     rtems_clock_get_boot_time_timeval( &tv );
0722   }
0723 
0724   CleanupChangeWork( tc );
0725 
0726   /*
0727    * Delete the change worker task.
0728    */
0729   DeleteTask( worker_id );
0730 }
0731 
0732 /**
0733  * @fn void T_case_body_ScoreTimecounterValGetSmp( void )
0734  */
0735 T_TEST_CASE( ScoreTimecounterValGetSmp )
0736 {
0737   ScoreTimecounterValGetSmp_Action_0();
0738 }
0739 
0740 /** @} */