LCOV - code coverage report
Current view: top level - disco/stem - fd_stem.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 41 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 639 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_stem_fd_stem_h
       2             : #define HEADER_fd_src_disco_stem_fd_stem_h
       3             : 
       4             : #include "../fd_disco_base.h"
       5             : #include "../sleep/fd_sleep.h"
       6             : 
       7           0 : #define FD_STEM_SCRATCH_ALIGN (128UL)
       8             : 
       9             : struct fd_stem_context {
      10             :    fd_frag_meta_t ** mcaches;
      11             :    ulong *           seqs;
      12             :    ulong *           depths;
      13             : 
      14             :    long              now;
      15             :    long              then;
      16             : 
      17             :    ulong *           cr_avail;
      18             :    ulong *           min_cr_avail;
      19             :    ulong             cr_decrement_amount;
      20             :    int *             out_reliable;
      21             :    ulong const *     cons_seq;
      22             :    struct fd_stem_tile_in * in;
      23             : 
      24             :    fd_sleep_t *            sleep;
      25             :    fd_sleep_wake_t const * wake;
      26             :    ushort const *          wake_off;
      27             :    ulong * const *         in_fseq;
      28             :    ulong const *           in_producer;
      29             : };
      30             : 
      31             : typedef struct fd_stem_context fd_stem_context_t;
      32             : 
      33             : struct fd_stem_sleep {
      34             :   fd_sleep_t *    shmem;
      35             : 
      36             :   ulong           tile_id;
      37             :   ulong const *   waker_fseq;  /* waker readiness word, NULL if not a client */
      38             :   ulong const *   out_link_id; /* per out: link id (seq_mirror), the tile's own array */
      39             :   ulong           in_link_id[ FD_SLEEP_IN_MAX ];               /* link id (seq_snap/sweep) */
      40             :   ulong           in_producer[ FD_SLEEP_IN_MAX ];              /* producer tile id, rung when credits return (ULONG_MAX if none) */
      41             :   fd_sleep_wake_t wake[ FD_SLEEP_OUT_MAX*FD_SLEEP_BITS_CNT ];  /* flattened (word,mask) pairs */
      42             :   ushort          wake_off[ FD_SLEEP_OUT_MAX+1UL ];            /* out_cnt+1 offsets into wake */
      43             : };
      44             : 
      45             : typedef struct fd_stem_sleep fd_stem_sleep_t;
      46             : 
      47             : struct __attribute__((aligned(64))) fd_stem_tile_in {
      48             :   fd_frag_meta_t const * mcache;   /* local join to this in's mcache */
      49             :   uint                   depth;    /* == fd_mcache_depth( mcache ), depth of this in's cache (const) */
      50             :   uint                   idx;      /* index of this in in the list of providers, [0, in_cnt) */
      51             :   ulong                  seq;      /* sequence number of next frag expected from the upstream producer,
      52             :                                       updated when frag from this in is published */
      53             :   fd_frag_meta_t const * mline;    /* == mcache + fd_mcache_line_idx( seq, depth ), location to poll next */
      54             :   ulong *                fseq;     /* local join to the fseq used to return flow control credits to the in */
      55             :   uint                   accum[6]; /* local diagnostic accumulators.  These are drained during in housekeeping. */
      56             :                                    /* Assumes FD_FSEQ_DIAG_{PUB_CNT,PUB_SZ,FILT_CNT,FILT_SZ,OVRNP_CNT,OVRNP_FRAG_CNT} are 0:5 */
      57             : };
      58             : 
      59             : typedef struct fd_stem_tile_in fd_stem_tile_in_t;
      60             : 
      61             : static inline ulong
      62             : fd_stem_publish( fd_stem_context_t * stem,
      63             :                  ulong               out_idx,
      64             :                  ulong               sig,
      65             :                  ulong               chunk,
      66             :                  ulong               sz,
      67             :                  ulong               ctl,
      68             :                  ulong               tsorig,
      69           0 :                  ulong               tspub ) {
      70           0 :   fd_frag_meta_t * mcache = stem->mcaches[ out_idx ];
      71           0 :   ulong            depth  = stem->depths [ out_idx ];
      72           0 :   ulong *          seqp   = &stem->seqs  [ out_idx ];
      73           0 :   ulong            seq    = *seqp;
      74           0 : # if FD_HAS_AVX
      75           0 :   fd_mcache_publish_avx( mcache, depth, seq, sig, chunk, sz, ctl, tsorig, tspub );
      76             : # elif FD_HAS_ARM
      77             :   fd_mcache_publish_arm( mcache, depth, seq, sig, chunk, sz, ctl, tsorig, tspub );
      78             : # else
      79             :   fd_mcache_publish    ( mcache, depth, seq, sig, chunk, sz, ctl, tsorig, tspub );
      80             : # endif
      81           0 :   if( FD_LIKELY( stem->out_reliable[ out_idx ] ) ) {
      82           0 :     if( FD_UNLIKELY( stem->cr_avail[ out_idx ]<stem->cr_decrement_amount ) ) { /* Ensure producer BURST is set correctly */
      83           0 :       FD_LOG_ERR(( "BURST underprovisioned out_idx=%lu cr_avail=%lu min_cr_avail=%lu cr_decrement_amount=%lu", out_idx, stem->cr_avail[ out_idx ], *stem->min_cr_avail, stem->cr_decrement_amount ));
      84           0 :     }
      85           0 :     stem->cr_avail[ out_idx ] -= stem->cr_decrement_amount;
      86           0 :     *stem->min_cr_avail        = fd_ulong_min( stem->cr_avail[ out_idx ], *stem->min_cr_avail );
      87           0 :   }
      88           0 :   *seqp = fd_seq_inc( seq, 1UL );
      89           0 :   if( FD_UNLIKELY( stem->sleep ) ) fd_sleep_wake_check( stem->sleep, stem->wake+stem->wake_off[ out_idx ], (ulong)(stem->wake_off[ out_idx+1UL ]-stem->wake_off[ out_idx ]) );
      90           0 :   return seq;
      91           0 : }
      92             : 
      93             : static inline ulong
      94             : fd_stem_advance( fd_stem_context_t * stem,
      95           0 :                  ulong               out_idx ) {
      96           0 :   ulong * seqp = &stem->seqs[ out_idx ];
      97           0 :   ulong   seq  = *seqp;
      98           0 :   if( FD_LIKELY( stem->out_reliable[ out_idx ] ) ) {
      99           0 :     if( FD_UNLIKELY( stem->cr_avail[ out_idx ]<stem->cr_decrement_amount ) ) { /* Ensure producer BURST is set correctly */
     100           0 :       FD_LOG_ERR(( "BURST underprovisioned out_idx=%lu cr_avail=%lu min_cr_avail=%lu cr_decrement_amount=%lu", out_idx, stem->cr_avail[ out_idx ], *stem->min_cr_avail, stem->cr_decrement_amount ));
     101           0 :     }
     102           0 :     stem->cr_avail[ out_idx ] -= stem->cr_decrement_amount;
     103           0 :     *stem->min_cr_avail        = fd_ulong_min( stem->cr_avail[ out_idx ], *stem->min_cr_avail );
     104           0 :   }
     105           0 :   *seqp = fd_seq_inc( seq, 1UL );
     106           0 :   if( FD_UNLIKELY( stem->sleep ) ) fd_sleep_wake_check( stem->sleep, stem->wake+stem->wake_off[ out_idx ], (ulong)(stem->wake_off[ out_idx+1UL ]-stem->wake_off[ out_idx ]) );
     107           0 :   return seq;
     108           0 : }
     109             : 
     110             : static inline void
     111             : fd_stem_credit_return( fd_stem_context_t * stem,
     112             :                        ulong               in_idx,
     113           0 :                        ulong               seq ) {
     114           0 :   __atomic_store_n( stem->in_fseq[ in_idx ], seq, __ATOMIC_RELEASE );
     115           0 :   if( FD_LIKELY( !stem->sleep ) ) return;
     116           0 :   ulong producer = stem->in_producer[ in_idx ];
     117           0 :   if( FD_UNLIKELY( producer==ULONG_MAX ) ) return;
     118           0 :   __atomic_thread_fence( __ATOMIC_SEQ_CST );
     119           0 :   if( FD_UNLIKELY( FD_VOLATILE_CONST( stem->sleep->credit_bits[ producer>>6 ] ) & (1UL<<(producer&63UL)) ) ) fd_sleep_ring( stem->sleep, producer );
     120           0 : }
     121             : 
     122             : #endif /* HEADER_fd_src_disco_stem_fd_stem_h */

Generated by: LCOV version 1.14