Line data Source code
1 : #include "fd_startup.h" 2 : #include "../disco/metrics/fd_metrics.h" 3 : #include <time.h> 4 : 5 : __attribute__((weak)) int volatile const fd_startup_skip_checks = 0; 6 : 7 : /* replay_status_laddr resolves the local address of the replay tile's 8 : RUNTIME_STATUS gauge, with defensive boilerplate to prevent 9 : segfault. */ 10 : 11 : static ulong volatile const * 12 0 : replay_status_laddr( fd_topo_t const * topo ) { 13 0 : ulong metric_wksp_id = fd_topo_find_wksp( topo, "metric_in" ); 14 0 : if( FD_UNLIKELY( metric_wksp_id==ULONG_MAX ) ) FD_LOG_ERR(( "This topology does not have a metric_in workspace" )); 15 : 16 0 : fd_topo_wksp_t const * metric_topo_wksp = &topo->workspaces[ metric_wksp_id ]; 17 0 : if( FD_UNLIKELY( !metric_topo_wksp->wksp ) ) FD_LOG_ERR(( "metric_in wksp is not joined" )); 18 : 19 0 : fd_wksp_t * metric_wksp = metric_topo_wksp->wksp; 20 0 : if( FD_UNLIKELY( !metric_wksp ) ) FD_LOG_ERR(( "metric_in wksp is not joined" )); 21 : 22 0 : if( FD_UNLIKELY( fd_shmem_join_query_by_join( metric_wksp, NULL )!=0 ) ) { 23 0 : FD_LOG_ERR(( "metric_in wksp not mapped into current tile" )); 24 0 : } 25 : 26 0 : ulong replay_tile_id = fd_topo_find_tile( topo, "replay", 0 ); 27 0 : if( FD_UNLIKELY( replay_tile_id==ULONG_MAX ) ) return NULL; /* dev topologies without replay never gate */ 28 0 : fd_topo_tile_t const * replay_tile = &topo->tiles[ replay_tile_id ]; 29 : 30 0 : fd_topo_obj_t const * metric_obj = fd_topo_find_tile_obj( topo, replay_tile, "metrics" ); 31 0 : if( FD_UNLIKELY( !metric_obj ) ) FD_LOG_ERR(( "replay:0 does not have a metrics object" )); 32 0 : if( FD_UNLIKELY( metric_obj->wksp_id!=metric_wksp_id ) ) FD_LOG_ERR(( "This tile does not have access to replay:0 metrics" )); 33 : 34 0 : ulong * replay_metrics = fd_topo_obj_laddr( topo, metric_obj->id ); 35 0 : if( FD_UNLIKELY( !replay_metrics ) ) FD_LOG_ERR(( "Cannot access replay:0 metrics" )); 36 : 37 0 : ulong volatile const * replay_tile_metrics = fd_metrics_tile( replay_metrics ); 38 0 : return &replay_tile_metrics[ MIDX( GAUGE, REPLAY, RUNTIME_STATUS ) ]; 39 0 : } 40 : 41 : void 42 : fd_startup_gate_init( fd_startup_gate_t * gate, 43 : fd_topo_t const * topo, 44 0 : ulong in_cnt ) { 45 0 : gate->status = fd_startup_skip_checks ? NULL : replay_status_laddr( topo ); 46 0 : gate->started = !gate->status; 47 0 : gate->idle_cnt = 0UL; 48 0 : gate->idle_max = 2UL*in_cnt+1UL; 49 0 : } 50 : 51 : int 52 0 : fd_startup_gate_idle( fd_startup_gate_t * gate ) { 53 0 : if( FD_LIKELY( gate->started ) ) return 1; 54 : 55 0 : if( FD_UNLIKELY( FD_VOLATILE_CONST( *gate->status ) ) ) { 56 0 : gate->started = 1; 57 0 : return 1; 58 0 : } 59 : 60 0 : gate->idle_cnt++; 61 0 : if( FD_LIKELY( gate->idle_cnt>=gate->idle_max ) ) { 62 0 : gate->idle_cnt = 0UL; 63 0 : struct timespec ts = { .tv_sec=0, .tv_nsec=(int)1e6 }; /* 1ms */ 64 0 : (void)clock_nanosleep( CLOCK_REALTIME, 0, &ts, NULL ); 65 0 : } 66 0 : return 0; 67 0 : }