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 6 : fd_clock_tile_init( fd_clock_tile_t * clock ) { 27 : /* fdctl calibrates tick_per_ns on startup, no need to calibrate here */ 28 6 : double init_w = (double)fd_tempo_tick_per_ns( NULL ); 29 : 30 6 : long init_x0, init_y0; 31 6 : int clock_err = fd_clock_joint_read( _fd_tickcount, NULL, fd_log_wallclock_host, NULL, &init_x0, &init_y0, NULL ); 32 6 : if( FD_UNLIKELY( clock_err ) ) FD_LOG_ERR(( "fd_clock_joint_read failed (%i-%s)", clock_err, fd_clock_strerror( clock_err ) )); 33 : 34 6 : long recal_avg = 10e6L; /* 10ms */ 35 6 : void * shclock = fd_clock_new( clock->shmem, recal_avg, 0L, 0., 0., init_x0, init_y0, init_w ); 36 6 : if( FD_UNLIKELY( !shclock ) ) FD_LOG_ERR(( "fd_clock_new failed" )); 37 : 38 6 : fd_clock_t * clock_ptr = fd_clock_join( clock->clock, shclock, _fd_tickcount, NULL ); 39 6 : if( FD_UNLIKELY( !clock_ptr ) ) FD_LOG_ERR(( "fd_clock_join failed" )); 40 : 41 6 : fd_clock_epoch_init( clock->epoch, clock->shmem ); 42 6 : } 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_now returns an approximation of fd_log_wallclock. */ 71 : 72 : static inline long 73 259810243 : fd_clock_tile_now( fd_clock_tile_t const * clock ) { 74 259810243 : return fd_clock_epoch_y( clock->epoch, fd_tickcount() ); 75 259810243 : } 76 : 77 : /* fd_clock_tile_recal_due returns 1 if a recalibration is due, else 0. */ 78 : 79 : static inline int 80 0 : fd_clock_tile_recal_due( fd_clock_tile_t * clock ) { 81 0 : return fd_clock_tile_now( clock ) >= fd_clock_tile_recal_next( clock ); 82 0 : } 83 : 84 : /* fd_clock_tile_tickcount_to_wallclock converts an fd_tickcount() 85 : sample to a fd_log_wallclock() estimate. */ 86 : 87 : static inline long 88 : fd_clock_tile_tickcount_to_wallclock( fd_clock_tile_t const * clock, 89 0 : long tickcount ) { 90 0 : return fd_clock_epoch_y( clock->epoch, tickcount ); 91 0 : } 92 : 93 : /* fd_clock_tile_tickcount_decomp decompresses a frag_meta compressed 94 : tickcount sample. */ 95 : 96 : static inline long 97 : fd_clock_tile_tickcount_decomp( fd_clock_tile_t const * clock, 98 0 : ulong ts_comp ) { 99 0 : long ref = clock->epoch->x0; 100 0 : return fd_frag_meta_ts_decomp( ts_comp, ref ); 101 0 : } 102 : 103 : FD_PROTOTYPES_END 104 : 105 : #endif /* HEADER_fd_src_disco_fd_clock_tile_h */