LCOV - code coverage report
Current view: top level - disco - fd_clock_tile.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 50 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 486 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_fd_clock_tile_h
       2             : #define HEADER_fd_src_disco_fd_clock_tile_h
       3             : 
       4             : /* fd_clock_tile.h provides fd_clock convenience APIs for tiles */
       5             : 
       6             : #include "../tango/tempo/fd_tempo.h"
       7             : #include "../util/clock/fd_clock.h"
       8             : 
       9             : /* fd_clock_tile_t is a fast nanosecond clock source for Firedancer
      10             :    tiles (single-threaded usage). */
      11             : 
      12             : struct fd_clock_tile {
      13             :   fd_clock_shmem_t shmem[1];
      14             :   fd_clock_t       clock[1];
      15             :   fd_clock_epoch_t epoch[1];
      16             :   double           inv_m;
      17             : };
      18             : 
      19             : typedef struct fd_clock_tile fd_clock_tile_t;
      20             : 
      21             : FD_PROTOTYPES_BEGIN
      22             : 
      23             : /* fd_clock_tile_init creates a new fd_clock_tile_t.  Assumes that the
      24             :    calling thread has pre-calibrated fd_tempo tick_per_ns value. */
      25             : 
      26             : static inline void
      27           0 : fd_clock_tile_init( fd_clock_tile_t * clock ) {
      28             :   /* fdctl calibrates tick_per_ns on startup, no need to calibrate here */
      29           0 :   double init_w = (double)fd_tempo_tick_per_ns( NULL );
      30             : 
      31           0 :   long init_x0, init_y0;
      32           0 :   int  clock_err = fd_clock_joint_read( _fd_tickcount, NULL, fd_log_wallclock_host, NULL, &init_x0, &init_y0, NULL );
      33           0 :   if( FD_UNLIKELY( clock_err ) ) FD_LOG_ERR(( "fd_clock_joint_read failed (%i-%s)", clock_err, fd_clock_strerror( clock_err ) ));
      34             : 
      35           0 :   long   recal_avg  = 10e6L; /* 10ms */
      36           0 :   void * shclock = fd_clock_new( clock->shmem, recal_avg, 0L, 0., 0., init_x0, init_y0, init_w );
      37           0 :   if( FD_UNLIKELY( !shclock ) ) FD_LOG_ERR(( "fd_clock_new failed" ));
      38             : 
      39           0 :   fd_clock_t * clock_ptr = fd_clock_join( clock->clock, shclock, _fd_tickcount, NULL );
      40           0 :   if( FD_UNLIKELY( !clock_ptr ) ) FD_LOG_ERR(( "fd_clock_join failed" ));
      41             : 
      42           0 :   fd_clock_epoch_init( clock->epoch, clock->shmem );
      43           0 :   clock->inv_m = 1.0/clock->epoch->m;
      44           0 : }
      45             : 
      46             : /* fd_clock_tile_recal_next returns the wallclock deadline after which
      47             :    the next recal should be done. */
      48             : 
      49             : static inline long
      50           0 : fd_clock_tile_recal_next( fd_clock_tile_t const * clock ) {
      51           0 :   return fd_clock_recal_next( clock->clock );
      52           0 : }
      53             : 
      54             : /* fd_clock_tile_recal is called periodically to synchronize tickcount
      55             :    to log_wallclock.  Returns the wallclock deadline after which the
      56             :    next recal should be done. */
      57             : 
      58             : static inline long
      59           0 : fd_clock_tile_recal( fd_clock_tile_t * clock ) {
      60           0 :   long x; long y;
      61           0 :   int err = fd_clock_joint_read( _fd_tickcount, NULL, fd_log_wallclock_host, NULL, &x, &y, NULL );
      62           0 :   if( FD_UNLIKELY( err ) ) {
      63             :     /* on recal fail, retry in 1ms */
      64           0 :     FD_LOG_WARNING(( "fd_clock_joint_read failed (%i-%s)", err, fd_clock_strerror( err ) ));
      65           0 :     return ( clock->shmem->recal_next = fd_clock_epoch_y( clock->epoch, fd_tickcount() ) + 1000000L );
      66           0 :   }
      67           0 :   long recal_next = fd_clock_recal( clock->clock, x, y );
      68           0 :   fd_clock_epoch_refresh( clock->epoch, clock->shmem );
      69           0 :   clock->inv_m = 1.0/clock->epoch->m;
      70           0 :   return recal_next;
      71           0 : }
      72             : 
      73             : /* fd_clock_tile_set re-anchors the clock to a caller-supplied
      74             :    wallclock.  For harnesses driving a virtual timeline. */
      75             : 
      76             : static inline void
      77             : fd_clock_tile_set( fd_clock_tile_t * clock,
      78           0 :                    long              now ) {
      79           0 :   fd_clock_step( clock->clock, fd_tickcount(), now, clock->epoch->w );
      80           0 :   fd_clock_epoch_refresh( clock->epoch, clock->shmem );
      81           0 :   clock->inv_m = 1.0/clock->epoch->m;
      82           0 : }
      83             : 
      84             : /* fd_clock_tile_now returns an approximation of fd_log_wallclock. */
      85             : 
      86             : static inline long
      87           0 : fd_clock_tile_now( fd_clock_tile_t const * clock ) {
      88           0 :   return fd_clock_epoch_y( clock->epoch, fd_tickcount() );
      89           0 : }
      90             : 
      91             : /* fd_clock_tile_recal_due returns 1 if a recalibration is due, else 0. */
      92             : 
      93             : static inline int
      94           0 : fd_clock_tile_recal_due( fd_clock_tile_t * clock ) {
      95           0 :   return fd_clock_tile_now( clock ) >= fd_clock_tile_recal_next( clock );
      96           0 : }
      97             : 
      98             : /* fd_clock_tile_tickcount_to_wallclock converts an fd_tickcount()
      99             :    sample to a fd_log_wallclock() estimate. */
     100             : 
     101             : static inline long
     102             : fd_clock_tile_tickcount_to_wallclock( fd_clock_tile_t const * clock,
     103           0 :                                       long                    tickcount ) {
     104           0 :   return fd_clock_epoch_y( clock->epoch, tickcount );
     105           0 : }
     106             : 
     107             : /* fd_clock_tile_wallclock_to_tickcount converts a fd_log_wallclock()
     108             :    value to the fd_tickcount() at which the clock would read it. */
     109             : 
     110             : static inline long
     111             : fd_clock_tile_wallclock_to_tickcount( fd_clock_tile_t const * clock,
     112           0 :                                       long                    wallclock ) {
     113           0 :   fd_clock_epoch_t const * epoch = clock->epoch;
     114           0 :   return fd_clock_epoch_x0( epoch ) + (long)( (double)( wallclock-fd_clock_epoch_y0_eff( epoch ) )*clock->inv_m );
     115           0 : }
     116             : 
     117             : /* fd_clock_tile_tickcomp_to_wallclock converts a compressed
     118             :    fd_tickcount() sample to a fd_log_wallclock() estimate. */
     119             : 
     120             : static inline long
     121             : fd_clock_tile_tickcomp_to_wallclock( fd_clock_tile_t const * clock,
     122           0 :                                      ulong                   ts_comp ) {
     123           0 :   long ts = fd_frag_meta_ts_decomp( ts_comp, clock->epoch->x0 );
     124           0 :   return fd_clock_tile_tickcount_to_wallclock( clock, ts );
     125           0 : }
     126             : 
     127             : FD_PROTOTYPES_END
     128             : 
     129             : #endif /* HEADER_fd_src_disco_fd_clock_tile_h */

Generated by: LCOV version 1.14