LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_progcache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 147 245 60.0 %
Date: 2026-03-19 18:19:27 Functions: 6 7 85.7 %

          Line data    Source code
       1             : #include "fd_progcache.h"
       2             : 
       3             : #define POOL_NAME       fd_prog_recp
       4       59596 : #define POOL_ELE_T      fd_progcache_rec_t
       5             : #define POOL_IDX_T      uint
       6       71875 : #define POOL_NEXT       map_next
       7             : #define POOL_IMPL_STYLE 2
       8             : #include "../../util/tmpl/fd_pool_para.c"
       9             : 
      10             : #define MAP_NAME              fd_prog_recm
      11       31231 : #define MAP_ELE_T             fd_progcache_rec_t
      12           0 : #define MAP_KEY_T             fd_funk_xid_key_pair_t
      13       29793 : #define MAP_KEY               pair
      14             : #define MAP_KEY_EQ(k0,k1)     fd_funk_xid_key_pair_eq((k0),(k1))
      15             : #define MAP_KEY_HASH(k0,seed) fd_funk_xid_key_pair_hash((k0),(seed))
      16       31222 : #define MAP_IDX_T             uint
      17       59606 : #define MAP_NEXT              map_next
      18          12 : #define MAP_MAGIC             (0xf173da2ce77ecdb8UL)
      19             : #define MAP_CUSTOM_CHAIN      1
      20             : #define MAP_IMPL_STYLE        2
      21             : #include "../../util/tmpl/fd_map_chain_para.c"
      22             : 
      23             : #define POOL_NAME       fd_prog_txnp
      24          36 : #define POOL_T          fd_progcache_txn_t
      25             : #define POOL_IDX_T      uint
      26         192 : #define POOL_NEXT       map_next
      27             : #define POOL_IMPL_STYLE 2
      28             : #include "../../util/tmpl/fd_pool.c"
      29             : 
      30             : #define  MAP_NAME              fd_prog_txnm
      31             : #define  MAP_ELE_T             fd_progcache_txn_t
      32             : #define  MAP_KEY_T             fd_funk_txn_xid_t
      33       55097 : #define  MAP_KEY               xid
      34             : #define  MAP_KEY_EQ(k0,k1)     fd_funk_txn_xid_eq((k0),(k1))
      35             : #define  MAP_KEY_HASH(k0,seed) fd_funk_txn_xid_hash((k0),(seed))
      36      229315 : #define  MAP_IDX_T             uint
      37      111893 : #define  MAP_NEXT              map_next
      38          12 : #define  MAP_MAGIC             (0xf173da2ce77ecdb9UL)
      39             : #define  MAP_IMPL_STYLE        2
      40             : #include "../../util/tmpl/fd_map_chain.c"
      41             : 
      42             : FD_FN_CONST ulong
      43          96 : fd_progcache_shmem_align( void ) {
      44          96 :   return fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max(
      45          96 :       alignof(fd_progcache_shmem_t),
      46          96 :       fd_prog_txnm_align() ),
      47          96 :       fd_prog_txnp_align() ),
      48          96 :       alignof(fd_progcache_txn_t) ),
      49          96 :       fd_prog_recm_align() ),
      50          96 :       fd_prog_recp_align() ),
      51          96 :       alignof(fd_progcache_rec_t) ),
      52          96 :       fd_alloc_align() );
      53          96 : }
      54             : 
      55             : FD_FN_CONST ulong
      56             : fd_progcache_shmem_footprint( ulong txn_max,
      57          24 :                               ulong rec_max ) {
      58          24 :   if( FD_UNLIKELY( txn_max>UINT_MAX ) ) return 0UL;
      59          24 :   if( FD_UNLIKELY( rec_max>UINT_MAX ) ) return 0UL;
      60             : 
      61          24 :   ulong l = FD_LAYOUT_INIT;
      62             : 
      63          24 :   l = FD_LAYOUT_APPEND( l, alignof(fd_progcache_shmem_t), sizeof(fd_progcache_shmem_t) );
      64             : 
      65          24 :   ulong txn_chain_cnt = fd_prog_txnm_chain_cnt_est( txn_max );
      66          24 :   l = FD_LAYOUT_APPEND( l, fd_prog_txnm_align(), fd_prog_txnm_footprint( txn_chain_cnt ) );
      67          24 :   l = FD_LAYOUT_APPEND( l, fd_prog_txnp_align(), fd_prog_txnp_footprint( txn_max ) );
      68             : 
      69          24 :   ulong rec_chain_cnt = fd_prog_recm_chain_cnt_est( rec_max );
      70          24 :   l = FD_LAYOUT_APPEND( l, fd_prog_recm_align(), fd_prog_recm_footprint( rec_chain_cnt ) );
      71          24 :   l = FD_LAYOUT_APPEND( l, fd_prog_recp_align(), fd_prog_recp_footprint() );
      72          24 :   l = FD_LAYOUT_APPEND( l, alignof(fd_progcache_rec_t), sizeof(fd_progcache_rec_t) * rec_max );
      73             : 
      74          24 :   l = FD_LAYOUT_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      75             : 
      76          24 :   return FD_LAYOUT_FINI( l, fd_progcache_shmem_align() );
      77          24 : }
      78             : 
      79             : fd_progcache_shmem_t *
      80             : fd_progcache_shmem_new( void * shmem,
      81             :                         ulong  wksp_tag,
      82             :                         ulong  seed,
      83             :                         ulong  txn_max,
      84          12 :                         ulong  rec_max ) {
      85          12 :   fd_progcache_shmem_t * pc   = shmem;
      86          12 :   fd_wksp_t *            wksp = fd_wksp_containing( pc );
      87             : 
      88          12 :   if( FD_UNLIKELY( !pc ) ) {
      89           0 :     FD_LOG_WARNING(( "NULL shmem" ));
      90           0 :     return NULL;
      91           0 :   }
      92             : 
      93          12 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)pc, fd_progcache_shmem_align() ) ) ) {
      94           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
      95           0 :     return NULL;
      96           0 :   }
      97             : 
      98          12 :   if( FD_UNLIKELY( !wksp_tag ) ) {
      99           0 :     FD_LOG_WARNING(( "bad wksp_tag" ));
     100           0 :     return NULL;
     101           0 :   }
     102             : 
     103          12 :   if( FD_UNLIKELY( !wksp ) ) {
     104           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     105           0 :     return NULL;
     106           0 :   }
     107             : 
     108          12 :   if( FD_UNLIKELY( !txn_max || txn_max>UINT_MAX ) ) {
     109           0 :     FD_LOG_WARNING(( "invalid txn_max" ));
     110           0 :     return NULL;
     111           0 :   }
     112             : 
     113          12 :   if( FD_UNLIKELY( !rec_max || rec_max>UINT_MAX ) ) {
     114           0 :     FD_LOG_WARNING(( "invalid rec_max" ));
     115           0 :     return NULL;
     116           0 :   }
     117             : 
     118          12 :   FD_SCRATCH_ALLOC_INIT( l, pc+1 );
     119             : 
     120          12 :   ulong txn_chain_cnt = fd_prog_txnm_chain_cnt_est( txn_max );
     121          12 :   void * txn_map = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_txnm_align(), fd_prog_txnm_footprint( txn_chain_cnt ) );
     122          12 :   void * txn_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_txnp_align(), fd_prog_txnp_footprint( txn_max ) );
     123             : 
     124           0 :   ulong rec_chain_cnt = fd_prog_recm_chain_cnt_est( rec_max );
     125          12 :   void * rec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_recm_align(), fd_prog_recm_footprint( rec_chain_cnt ) );
     126          12 :   void * rec_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_recp_align(), fd_prog_recp_footprint() );
     127          12 :   fd_progcache_rec_t * rec_ele = (fd_progcache_rec_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_progcache_rec_t), sizeof(fd_progcache_rec_t) * rec_max );
     128             : 
     129          12 :   void * alloc = FD_SCRATCH_ALLOC_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
     130             : 
     131          12 :   FD_TEST( _l == (ulong)pc + fd_progcache_shmem_footprint( txn_max, rec_max ) );
     132             : 
     133          12 :   fd_memset( pc, 0, sizeof(fd_progcache_shmem_t) );
     134             : 
     135          12 :   pc->wksp_tag = wksp_tag;
     136          12 :   pc->seed     = seed;
     137             : 
     138          12 :   pc->txn.map_gaddr = fd_wksp_gaddr_fast( wksp, fd_prog_txnm_new( txn_map, txn_chain_cnt, seed ) );
     139          12 :   void * txn_pool2 = fd_prog_txnp_new( txn_pool, txn_max );
     140          12 :   pc->txn.pool_gaddr = fd_wksp_gaddr_fast( wksp, txn_pool2 );
     141          12 :   fd_progcache_txn_t * txn_ele = fd_prog_txnp_join( txn_pool2 );
     142          12 :   pc->txn.ele_gaddr = fd_wksp_gaddr_fast( wksp, txn_ele );
     143          12 :   fd_prog_txnp_leave( txn_ele );
     144          12 :   pc->txn.max = txn_max;
     145          12 :   pc->txn.child_head_idx = UINT_MAX;
     146          12 :   pc->txn.child_tail_idx = UINT_MAX;
     147          12 :   fd_funk_txn_xid_set_root( pc->txn.last_publish );
     148         204 :   for( ulong i=0UL; i<txn_max; i++ ) {
     149         192 :     fd_rwlock_new( &txn_ele[ i ].lock );
     150         192 :   }
     151             : 
     152          12 :   pc->rec.map_gaddr = fd_wksp_gaddr_fast( wksp, fd_prog_recm_new( rec_map, rec_chain_cnt, seed ) );
     153          12 :   void * rec_pool2 = fd_prog_recp_new( rec_pool );
     154          12 :   pc->rec.pool_gaddr = fd_wksp_gaddr_fast( wksp, rec_pool2 );
     155          12 :   fd_prog_recp_t rec_join[1];
     156          12 :   fd_prog_recp_join( rec_join, rec_pool2, rec_ele, rec_max );
     157          12 :   fd_prog_recp_reset( rec_join, 0UL );
     158          12 :   pc->rec.ele_gaddr = fd_wksp_gaddr_fast( wksp, rec_ele );
     159          12 :   fd_prog_recp_leave( rec_join );
     160          12 :   pc->rec.max = (uint)rec_max;
     161       12300 :   for( ulong i=0UL; i<rec_max; i++ ) {
     162       12288 :     fd_rwlock_new( &rec_ele[ i ].lock );
     163       12288 :   }
     164             : 
     165          12 :   fd_rwlock_new( &pc->clock.lock );
     166          12 :   pc->clock.head = 0U;
     167             : 
     168          12 :   fd_rwlock_new( &pc->spill.lock );
     169          12 :   pc->spill.spad_used = 0U;
     170             : 
     171          12 :   pc->alloc_gaddr = fd_wksp_gaddr_fast( wksp, fd_alloc_join( fd_alloc_new( alloc, wksp_tag ), 0UL ) );
     172             : 
     173          12 :   FD_COMPILER_MFENCE();
     174          12 :   FD_VOLATILE( pc->magic ) = FD_PROGCACHE_SHMEM_MAGIC;
     175          12 :   FD_COMPILER_MFENCE();
     176             : 
     177          12 :   return (void *)pc;
     178          12 : }
     179             : 
     180             : fd_progcache_join_t *
     181             : fd_progcache_shmem_join( fd_progcache_join_t *  ljoin,
     182          12 :                          fd_progcache_shmem_t * shmem ) {
     183             : 
     184          12 :   if( FD_UNLIKELY( !shmem ) ) {
     185           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     186           0 :     return NULL;
     187           0 :   }
     188          12 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
     189           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
     190           0 :     return NULL;
     191           0 :   }
     192          12 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
     193          12 :   if( FD_UNLIKELY( !wksp ) ) {
     194           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     195           0 :     return NULL;
     196           0 :   }
     197          12 :   if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
     198           0 :     FD_LOG_WARNING(( "bad magic" ));
     199           0 :     return NULL;
     200           0 :   }
     201             : 
     202          12 :   if( FD_UNLIKELY( !ljoin ) ) {
     203           0 :     FD_LOG_WARNING(( "NULL join" ));
     204           0 :     return NULL;
     205           0 :   }
     206             : 
     207          12 :   memset( ljoin, 0, sizeof(fd_progcache_join_t) );
     208             : 
     209          12 :   ljoin->shmem = shmem;
     210          12 :   ljoin->wksp  = wksp;
     211             : 
     212          12 :   ljoin->txn.pool = fd_prog_txnp_join( fd_wksp_laddr( wksp, shmem->txn.pool_gaddr ) );
     213          12 :   if( FD_UNLIKELY( !ljoin->txn.pool ) ) {
     214           0 :     FD_LOG_WARNING(( "fd_prog_txnp_join failed" ));
     215           0 :     return NULL;
     216           0 :   }
     217          12 :   ljoin->txn.map = fd_prog_txnm_join( fd_wksp_laddr( wksp, shmem->txn.map_gaddr ) );
     218          12 :   if( FD_UNLIKELY( !ljoin->txn.map ) ) {
     219           0 :     FD_LOG_WARNING(( "fd_prog_txnm_join failed" ));
     220           0 :     return NULL;
     221           0 :   }
     222          12 :   if( FD_UNLIKELY( !fd_prog_recm_join( ljoin->rec.map, fd_wksp_laddr( wksp, shmem->rec.map_gaddr ), fd_wksp_laddr( wksp, shmem->rec.ele_gaddr ), shmem->rec.max ) ) ) {
     223           0 :     FD_LOG_WARNING(( "fd_prog_recm_join failed" ));
     224           0 :     return NULL;
     225           0 :   }
     226          12 :   if( FD_UNLIKELY( !fd_prog_recp_join( ljoin->rec.pool, fd_wksp_laddr( wksp, shmem->rec.pool_gaddr ), fd_wksp_laddr( wksp, shmem->rec.ele_gaddr ), shmem->rec.max ) ) ) {
     227           0 :     FD_LOG_WARNING(( "fd_prog_recp_join failed" ));
     228           0 :     return NULL;
     229           0 :   }
     230             : 
     231          12 :   if( FD_UNLIKELY( !( ljoin->alloc = fd_alloc_join( fd_wksp_laddr( wksp, shmem->alloc_gaddr ), fd_tile_idx() ) ) ) ) {
     232           0 :     FD_LOG_WARNING(( "fd_alloc_join failed" ));
     233           0 :     return NULL;
     234           0 :   }
     235             : 
     236          12 :   return ljoin;
     237          12 : }
     238             : 
     239             : void *
     240             : fd_progcache_shmem_leave( fd_progcache_join_t *   ljoin,
     241          12 :                           fd_progcache_shmem_t ** opt_shmem ) {
     242             : 
     243          12 :   if( FD_UNLIKELY( !ljoin ) ) {
     244           0 :     FD_LOG_WARNING(( "NULL join" ));
     245           0 :     if( opt_shmem ) *opt_shmem = NULL;
     246           0 :     return NULL;
     247           0 :   }
     248             : 
     249          12 :   void * shmem = ljoin->shmem;
     250             : 
     251          12 :   memset( ljoin, 0, sizeof(fd_progcache_join_t) );
     252             : 
     253          12 :   if( opt_shmem ) *opt_shmem = shmem;
     254          12 :   return shmem;
     255          12 : }
     256             : 
     257             : void *
     258          12 : fd_progcache_shmem_delete( fd_progcache_shmem_t * shmem ) {
     259             : 
     260          12 :   if( FD_UNLIKELY( !shmem ) ) {
     261           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     262           0 :     return NULL;
     263           0 :   }
     264             : 
     265          12 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
     266           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
     267           0 :     return NULL;
     268           0 :   }
     269             : 
     270          12 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
     271          12 :   if( FD_UNLIKELY( !wksp ) ) {
     272           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     273           0 :     return NULL;
     274           0 :   }
     275             : 
     276          12 :   if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
     277           0 :     FD_LOG_WARNING(( "bad magic" ));
     278           0 :     return NULL;
     279           0 :   }
     280             : 
     281             :   /* Free all fd_alloc allocations made, individually
     282             :      (FIXME consider walking the element pool instead of the map?) */
     283             : 
     284          12 :   fd_alloc_t * alloc = fd_alloc_join( fd_wksp_laddr_fast( wksp, shmem->alloc_gaddr ), fd_tile_idx() );
     285             : 
     286          12 :   void * shmap = fd_wksp_laddr_fast( wksp, shmem->rec.map_gaddr );
     287          12 :   void * shele = fd_wksp_laddr_fast( wksp, shmem->rec.ele_gaddr );
     288          12 :   fd_prog_recm_t rec_map[1];
     289          12 :   if( FD_UNLIKELY( !fd_prog_recm_join( rec_map, shmap, shele, 0UL ) ) ) {
     290           0 :     FD_LOG_ERR(( "failed to join rec_map (corrupt funk?)" ));
     291           0 :     return NULL;
     292           0 :   }
     293          12 :   ulong chain_cnt = fd_prog_recm_chain_cnt( rec_map );
     294        6156 :   for( ulong chain_idx=0UL; chain_idx<chain_cnt; chain_idx++ ) {
     295        6144 :     for(
     296        6144 :         fd_prog_recm_iter_t iter = fd_prog_recm_iter( rec_map, chain_idx );
     297        6144 :         !fd_prog_recm_iter_done( iter );
     298        6144 :         iter = fd_prog_recm_iter_next( iter )
     299        6144 :     ) {
     300           0 :       fd_progcache_rec_t * rec = fd_prog_recm_iter_ele( iter );
     301           0 :       if( rec->data_gaddr ) {
     302           0 :         fd_alloc_free( alloc, fd_wksp_laddr_fast( wksp, rec->data_gaddr ) );
     303           0 :       }
     304           0 :       rec->data_gaddr = 0UL;
     305           0 :       rec->data_max   = 0U;
     306           0 :     }
     307        6144 :   }
     308             : 
     309          12 :   fd_prog_recm_leave( rec_map );
     310             : 
     311          12 :   FD_COMPILER_MFENCE();
     312          12 :   FD_VOLATILE( shmem->magic ) = 0UL;
     313          12 :   FD_COMPILER_MFENCE();
     314             : 
     315             :   /* Free the fd_alloc instance */
     316             : 
     317          12 :   fd_wksp_free_laddr( fd_alloc_delete( fd_alloc_leave( alloc ) ) );
     318             : 
     319          12 :   return shmem;
     320          12 : }
     321             : 
     322             : void *
     323           0 : fd_progcache_shmem_delete_fast( fd_progcache_shmem_t * shmem ) {
     324             : 
     325           0 :   if( FD_UNLIKELY( !shmem ) ) {
     326           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     327           0 :     return NULL;
     328           0 :   }
     329             : 
     330           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
     331           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
     332           0 :     return NULL;
     333           0 :   }
     334             : 
     335           0 :   if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
     336           0 :     FD_LOG_WARNING(( "bad magic" ));
     337           0 :     return NULL;
     338           0 :   }
     339             : 
     340           0 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
     341           0 :   if( FD_UNLIKELY( !wksp ) ) {
     342           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     343           0 :     return NULL;
     344           0 :   }
     345             : 
     346           0 :   ulong const tags[1] = { shmem->wksp_tag };
     347           0 :   fd_wksp_tag_free( wksp, tags, 1UL );
     348             : 
     349           0 :   return shmem;
     350           0 : }

Generated by: LCOV version 1.14