LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_progcache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 192 266 72.2 %
Date: 2026-06-29 05:51:35 Functions: 7 7 100.0 %

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

Generated by: LCOV version 1.14