LCOV - code coverage report
Current view: top level - disco - fd_clock_tile.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 15 43 34.9 %
Date: 2026-09-17 04:28:31 Functions: 7 456 1.5 %

          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             : };
      17             : 
      18             : typedef struct fd_clock_tile fd_clock_tile_t;
      19             : 
      20             : FD_PROTOTYPES_BEGIN
      21             : 
      22             : /* fd_clock_tile_init creates a new fd_clock_tile_t.  Assumes that the
      23             :    calling thread has pre-calibrated fd_tempo tick_per_ns value. */
      24             : 
      25             : static inline void
      26          60 : fd_clock_tile_init( fd_clock_tile_t * clock ) {
      27             :   /* fdctl calibrates tick_per_ns on startup, no need to calibrate here */
      28          60 :   double init_w = (double)fd_tempo_tick_per_ns( NULL );
      29             : 
      30          60 :   long init_x0, init_y0;
      31          60 :   int  clock_err = fd_clock_joint_read( _fd_tickcount, NULL, fd_log_wallclock_host, NULL, &init_x0, &init_y0, NULL );
      32          60 :   if( FD_UNLIKELY( clock_err ) ) FD_LOG_ERR(( "fd_clock_joint_read failed (%i-%s)", clock_err, fd_clock_strerror( clock_err ) ));
      33             : 
      34          60 :   long   recal_avg  = 10e6L; /* 10ms */
      35          60 :   void * shclock = fd_clock_new( clock->shmem, recal_avg, 0L, 0., 0., init_x0, init_y0, init_w );
      36          60 :   if( FD_UNLIKELY( !shclock ) ) FD_LOG_ERR(( "fd_clock_new failed" ));
      37             : 
      38          60 :   fd_clock_t * clock_ptr = fd_clock_join( clock->clock, shclock, _fd_tickcount, NULL );
      39          60 :   if( FD_UNLIKELY( !clock_ptr ) ) FD_LOG_ERR(( "fd_clock_join failed" ));
      40             : 
      41          60 :   fd_clock_epoch_init( clock->epoch, clock->shmem );
      42          60 : }
      43             : 
      44             : /* fd_clock_tile_recal_next returns the wallclock deadline after which
      45             :    the next recal should be done. */
      46             : 
      47             : static inline long
      48           0 : fd_clock_tile_recal_next( fd_clock_tile_t const * clock ) {
      49           0 :   return fd_clock_recal_next( clock->clock );
      50           0 : }
      51             : 
      52             : /* fd_clock_tile_recal is called periodically to synchronize tickcount
      53             :    to log_wallclock.  Returns the wallclock deadline after which the
      54             :    next recal should be done. */
      55             : 
      56             : static inline long
      57           0 : fd_clock_tile_recal( fd_clock_tile_t * clock ) {
      58           0 :   long x; long y;
      59           0 :   int err = fd_clock_joint_read( _fd_tickcount, NULL, fd_log_wallclock_host, NULL, &x, &y, NULL );
      60           0 :   if( FD_UNLIKELY( err ) ) {
      61             :     /* on recal fail, retry in 1ms */
      62           0 :     FD_LOG_WARNING(( "fd_clock_joint_read failed (%i-%s)", err, fd_clock_strerror( err ) ));
      63           0 :     return ( clock->shmem->recal_next = fd_clock_epoch_y( clock->epoch, fd_tickcount() ) + 1000000L );
      64           0 :   }
      65           0 :   long recal_next = fd_clock_recal( clock->clock, x, y );
      66           0 :   fd_clock_epoch_refresh( clock->epoch, clock->shmem );
      67           0 :   return recal_next;
      68           0 : }
      69             : 
      70             : /* fd_clock_tile_set re-anchors the clock to a caller-supplied
      71             :    wallclock.  For harnesses driving a virtual timeline. */
      72             : 
      73             : static inline void
      74             : fd_clock_tile_set( fd_clock_tile_t * clock,
      75           0 :                    long              now ) {
      76           0 :   fd_clock_step( clock->clock, fd_tickcount(), now, clock->epoch->w );
      77           0 :   fd_clock_epoch_refresh( clock->epoch, clock->shmem );
      78           0 : }
      79             : 
      80             : /* fd_clock_tile_now returns an approximation of fd_log_wallclock. */
      81             : 
      82             : static inline long
      83   262404437 : fd_clock_tile_now( fd_clock_tile_t const * clock ) {
      84   262404437 :   return fd_clock_epoch_y( clock->epoch, fd_tickcount() );
      85   262404437 : }
      86             : 
      87             : /* fd_clock_tile_recal_due returns 1 if a recalibration is due, else 0. */
      88             : 
      89             : static inline int
      90           0 : fd_clock_tile_recal_due( fd_clock_tile_t * clock ) {
      91           0 :   return fd_clock_tile_now( clock ) >= fd_clock_tile_recal_next( clock );
      92           0 : }
      93             : 
      94             : /* fd_clock_tile_tickcount_to_wallclock converts an fd_tickcount()
      95             :    sample to a fd_log_wallclock() estimate. */
      96             : 
      97             : static inline long
      98             : fd_clock_tile_tickcount_to_wallclock( fd_clock_tile_t const * clock,
      99           0 :                                       long                    tickcount ) {
     100           0 :   return fd_clock_epoch_y( clock->epoch, tickcount );
     101           0 : }
     102             : 
     103             : /* fd_clock_tile_tickcomp_to_wallclock converts a compressed
     104             :    fd_tickcount() sample to a fd_log_wallclock() estimate. */
     105             : 
     106             : static inline long
     107             : fd_clock_tile_tickcomp_to_wallclock( fd_clock_tile_t const * clock,
     108           0 :                                      ulong                   ts_comp ) {
     109           0 :   long ts = fd_frag_meta_ts_decomp( ts_comp, clock->epoch->x0 );
     110           0 :   return fd_clock_tile_tickcount_to_wallclock( clock, ts );
     111           0 : }
     112             : 
     113             : FD_PROTOTYPES_END
     114             : 
     115             : #endif /* HEADER_fd_src_disco_fd_clock_tile_h */

Generated by: LCOV version 1.14