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

Generated by: LCOV version 1.14