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-09-17 04:28:31 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             : #include <stdatomic.h>
      18             : 
      19           0 : #define FD_NODE_INFO_MAGIC (0xf17eda2c4e490000UL) /* firedancer ni ver 0 */
      20             : 
      21             : struct fd_node_info {
      22             :   /* fields are zero until known */
      23             :   fd_pubkey_t vote_account;
      24             :   fd_pubkey_t identity;
      25             :   fd_hash_t   genesis_hash;
      26             : };
      27             : 
      28             : typedef struct fd_node_info fd_node_info_t;
      29             : 
      30             : struct fd_node_info_box {
      31             :   ulong        magic;     /* ==FD_NODE_INFO_MAGIC */
      32             :   _Atomic uint seq_lock;  /* lsb==1 implies active write */
      33             : 
      34             :   fd_node_info_t info;
      35             : };
      36             : 
      37             : typedef struct fd_node_info_box fd_node_info_box_t;
      38             : 
      39             : FD_PROTOTYPES_BEGIN
      40             : 
      41             : static inline void *
      42           0 : fd_node_info_box_new( void * shmem ) {
      43           0 :   fd_node_info_box_t * ni = (fd_node_info_box_t *)shmem;
      44           0 :   if( FD_UNLIKELY( !ni ) ) {
      45           0 :     FD_LOG_WARNING(( "NULL shmem" ));
      46           0 :     return NULL;
      47           0 :   }
      48           0 :   fd_memset( ni, 0, sizeof(fd_node_info_box_t) );
      49           0 :   FD_VOLATILE( ni->magic ) = FD_NODE_INFO_MAGIC;
      50           0 :   return (void *)ni;
      51           0 : }
      52             : 
      53             : static inline fd_node_info_box_t *
      54           0 : fd_node_info_box_join( void * shni ) {
      55           0 :   if( FD_UNLIKELY( !shni ) ) {
      56           0 :     FD_LOG_WARNING(( "NULL shni" ));
      57           0 :     return NULL;
      58           0 :   }
      59           0 :   fd_node_info_box_t * ni = (fd_node_info_box_t *)shni;
      60           0 :   if( FD_UNLIKELY( ni->magic!=FD_NODE_INFO_MAGIC ) ) {
      61           0 :     FD_LOG_WARNING(( "bad magic" ));
      62           0 :     return NULL;
      63           0 :   }
      64           0 :   return ni;
      65           0 : }
      66             : 
      67             : /* fd_node_info_read does an atomic read of a shared fd_node_info_t. */
      68             : 
      69             : static inline fd_node_info_t *
      70             : fd_node_info_read( fd_node_info_t *           dst,
      71           0 :                    fd_node_info_box_t const * src ) {
      72           0 :   for(;;) {
      73           0 :     uint lock0 = atomic_load_explicit( &src->seq_lock, memory_order_acquire );
      74           0 :     memcpy( dst, &src->info, sizeof(fd_node_info_t) );
      75           0 :     atomic_thread_fence( memory_order_acquire );
      76           0 :     uint lock1 = atomic_load_explicit( &src->seq_lock, memory_order_relaxed );
      77           0 :     if( FD_LIKELY( lock0==lock1 && !(lock0 & 1U) ) ) break;
      78           0 :     FD_SPIN_PAUSE();
      79           0 :   }
      80           0 :   return dst;
      81           0 : }
      82             : 
      83             : /* fd_node_info_write_{begin,end} are used to gain exclusive access to a
      84             :    node_info for writes. */
      85             : 
      86             : static inline void
      87           0 : fd_node_info_write_begin( fd_node_info_box_t * dst ) {
      88           0 :   for(;;) {
      89           0 :     uint lock = atomic_load_explicit( &dst->seq_lock, memory_order_relaxed );
      90           0 :     if( FD_LIKELY( !(lock & 1U) &&
      91           0 :         atomic_compare_exchange_weak_explicit( &dst->seq_lock, &lock, lock+1U,
      92           0 :                                                memory_order_acquire, memory_order_relaxed ) ) ) {
      93           0 :       break;
      94           0 :     }
      95           0 :     FD_SPIN_PAUSE();
      96           0 :   }
      97           0 : }
      98             : 
      99             : static inline void
     100           0 : fd_node_info_write_end( fd_node_info_box_t * dst ) {
     101             :   atomic_fetch_add_explicit( &dst->seq_lock, 1U, memory_order_release );
     102           0 : }
     103             : 
     104             : FD_PROTOTYPES_END
     105             : 
     106             : #endif /* HEADER_fd_src_disco_node_info_fd_node_info_h */

Generated by: LCOV version 1.14