LCOV - code coverage report
Current view: top level - disco/node_info - fd_node_info.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 47 0.0 %
Date: 2026-06-30 05:50:37 Functions: 0 40 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_node_info_fd_node_info_h
       2             : #define HEADER_fd_src_disco_node_info_fd_node_info_h
       3             : 
       4             : /* fd_node_info provides a shared topology object that holds
       5             :    validator-level information which cannot be represented as simple
       6             :    scalar metrics (e.g. 32-byte public keys and hashes).
       7             : 
       8             :    The replay tile (identity, genesis hash) and the tower tile (vote
       9             :    account) write it.  The watch command and other consumers read it in
      10             :    a lock-free manner.
      11             : 
      12             :    The seqlock read/write helpers require atomics. */
      13             : 
      14             : #include "../../util/log/fd_log.h"
      15             : #include "../../flamenco/fd_flamenco_base.h"
      16             : 
      17             : FD_STATIC_ASSERT( FD_HAS_ATOMIC, fd_node_info requires atomics );
      18             : 
      19             : #include <stdatomic.h>
      20             : 
      21           0 : #define FD_NODE_INFO_MAGIC (0xf17eda2c4e490000UL) /* firedancer ni ver 0 */
      22             : 
      23             : struct fd_node_info {
      24             :   /* fields are zero until known */
      25             :   fd_pubkey_t vote_account;
      26             :   fd_pubkey_t identity;
      27             :   fd_hash_t   genesis_hash;
      28             : };
      29             : 
      30             : typedef struct fd_node_info fd_node_info_t;
      31             : 
      32             : struct fd_node_info_box {
      33             :   ulong        magic;     /* ==FD_NODE_INFO_MAGIC */
      34             :   _Atomic uint seq_lock;  /* lsb==1 implies active write */
      35             : 
      36             :   fd_node_info_t info;
      37             : };
      38             : 
      39             : typedef struct fd_node_info_box fd_node_info_box_t;
      40             : 
      41             : FD_PROTOTYPES_BEGIN
      42             : 
      43             : static inline void *
      44           0 : fd_node_info_box_new( void * shmem ) {
      45           0 :   fd_node_info_box_t * ni = (fd_node_info_box_t *)shmem;
      46           0 :   if( FD_UNLIKELY( !ni ) ) {
      47           0 :     FD_LOG_WARNING(( "NULL shmem" ));
      48           0 :     return NULL;
      49           0 :   }
      50           0 :   fd_memset( ni, 0, sizeof(fd_node_info_box_t) );
      51           0 :   FD_VOLATILE( ni->magic ) = FD_NODE_INFO_MAGIC;
      52           0 :   return (void *)ni;
      53           0 : }
      54             : 
      55             : static inline fd_node_info_box_t *
      56           0 : fd_node_info_box_join( void * shni ) {
      57           0 :   if( FD_UNLIKELY( !shni ) ) {
      58           0 :     FD_LOG_WARNING(( "NULL shni" ));
      59           0 :     return NULL;
      60           0 :   }
      61           0 :   fd_node_info_box_t * ni = (fd_node_info_box_t *)shni;
      62           0 :   if( FD_UNLIKELY( ni->magic!=FD_NODE_INFO_MAGIC ) ) {
      63           0 :     FD_LOG_WARNING(( "bad magic" ));
      64           0 :     return NULL;
      65           0 :   }
      66           0 :   return ni;
      67           0 : }
      68             : 
      69             : #if FD_HAS_ATOMIC
      70             : 
      71             : /* fd_node_info_read does an atomic read of a shared fd_node_info_t. */
      72             : 
      73             : static inline fd_node_info_t *
      74             : fd_node_info_read( fd_node_info_t *           dst,
      75           0 :                    fd_node_info_box_t const * src ) {
      76           0 :   for(;;) {
      77           0 :     uint lock0 = atomic_load_explicit( &src->seq_lock, memory_order_acquire );
      78           0 :     memcpy( dst, &src->info, sizeof(fd_node_info_t) );
      79           0 :     atomic_thread_fence( memory_order_acquire );
      80           0 :     uint lock1 = atomic_load_explicit( &src->seq_lock, memory_order_relaxed );
      81           0 :     if( FD_LIKELY( lock0==lock1 && !(lock0 & 1U) ) ) break;
      82           0 :     FD_SPIN_PAUSE();
      83           0 :   }
      84           0 :   return dst;
      85           0 : }
      86             : 
      87             : /* fd_node_info_write_{begin,end} are used to gain exclusive access to a
      88             :    node_info for writes. */
      89             : 
      90             : static inline void
      91           0 : fd_node_info_write_begin( fd_node_info_box_t * dst ) {
      92           0 :   for(;;) {
      93           0 :     uint lock = atomic_load_explicit( &dst->seq_lock, memory_order_relaxed );
      94           0 :     if( FD_LIKELY( !(lock & 1U) &&
      95           0 :         atomic_compare_exchange_weak_explicit( &dst->seq_lock, &lock, lock+1U,
      96           0 :                                                memory_order_acquire, memory_order_relaxed ) ) ) {
      97           0 :       break;
      98           0 :     }
      99           0 :     FD_SPIN_PAUSE();
     100           0 :   }
     101           0 : }
     102             : 
     103             : static inline void
     104           0 : fd_node_info_write_end( fd_node_info_box_t * dst ) {
     105             :   atomic_fetch_add_explicit( &dst->seq_lock, 1U, memory_order_release );
     106           0 : }
     107             : 
     108             : #endif /* FD_HAS_ATOMIC */
     109             : 
     110             : FD_PROTOTYPES_END
     111             : 
     112             : #endif /* HEADER_fd_src_disco_node_info_fd_node_info_h */

Generated by: LCOV version 1.14