LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_progcache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 218 282 77.3 %
Date: 2026-09-17 04:28:31 Functions: 12 12 100.0 %

          Line data    Source code
       1             : #include "fd_progcache.h"
       2             : #include "fd_progcache_clock.h"
       3             : 
       4             : #define MAP_NAME              fd_prog_recm
       5     2748292 : #define MAP_ELE_T             fd_progcache_rec_t
       6        1029 : #define MAP_KEY_T             fd_progcache_rec_key_t
       7      918055 : #define MAP_KEY               pair
       8             : #define MAP_KEY_EQ(k0,k1)     fd_progcache_rec_key_eq((k0),(k1))
       9             : #define MAP_KEY_HASH(k0,seed) fd_progcache_rec_key_hash( &(k0)->prog, (seed) )
      10     2747857 : #define MAP_IDX_T             uint
      11     2665731 : #define MAP_NEXT              map_next
      12         204 : #define MAP_MAGIC             (0xf173da2ce77ecdb8UL)
      13             : #define MAP_IMPL_STYLE        2
      14             : #include "../../util/tmpl/fd_map_chain_para.c"
      15             : 
      16             : #define POOL_NAME       fd_prog_txnp
      17         654 : #define POOL_T          fd_progcache_txn_t
      18             : #define POOL_IDX_T      uint
      19        3696 : #define POOL_NEXT       map_next
      20             : #define POOL_IMPL_STYLE 2
      21             : #include "../../util/tmpl/fd_pool.c"
      22             : 
      23             : #define  MAP_NAME              fd_prog_txnm
      24             : #define  MAP_ELE_T             fd_progcache_txn_t
      25        4575 : #define  MAP_KEY               xid
      26      928708 : #define  MAP_IDX_T             uint
      27        9282 : #define  MAP_NEXT              map_next
      28         204 : #define  MAP_MAGIC             (0xf173da2ce77ecdb9UL)
      29             : #define  MAP_IMPL_STYLE        2
      30             : #include "../../util/tmpl/fd_map_chain.c"
      31             : 
      32             : /* Metadata one record costs: the record and its map chain. */
      33             : 
      34       14514 : #define FD_PROGCACHE_REC_META_SZ ( sizeof(fd_progcache_rec_t)                 + \
      35       14514 :                                    sizeof(fd_prog_recm_shmem_private_chain_t) )
      36             : 
      37             : /* fd_progcache_slot_cost returns the amount of memory a single slot consumes. */
      38             : FD_FN_CONST static inline ulong
      39       14514 : fd_progcache_slot_cost( ulong c ) {
      40       14514 :   return fd_progcache_cache_slot_sz[ c ] + FD_PROGCACHE_REC_META_SZ;
      41       14514 : }
      42             : 
      43             : /* fd_progcache_arena_sz returns the amount of memory an entire arena
      44             :    (with slot_cnt[c] for each class c) consumes. */
      45             : static ulong
      46         204 : fd_progcache_arena_sz( ulong const * slot_cnt ) {
      47         204 :   ulong sz = 0UL;
      48        1428 :   for( ulong c=0UL; c<FD_PROGCACHE_CACHE_CLASS_CNT; c++ ) {
      49        1224 :     sz += slot_cnt[ c ]*fd_progcache_cache_slot_sz[ c ];
      50        1224 :   }
      51         204 :   return sz;
      52         204 : }
      53             : 
      54             : /* fd_progcache_layout_footprint returns the exact shmem footprint of a cache
      55             :    holding txn_max transactions, rec_max records and arena_sz bytes of value arena.
      56             :    fd_progcache_new lays out these same regions in this same order. */
      57             : static ulong
      58             : fd_progcache_layout_footprint( ulong txn_max,
      59             :                                ulong rec_max,
      60        1611 :                                ulong arena_sz ) {
      61        1611 :   ulong l = FD_LAYOUT_INIT;
      62             : 
      63        1611 :   l = FD_LAYOUT_APPEND( l, alignof(fd_progcache_shmem_t), sizeof(fd_progcache_shmem_t) );
      64             : 
      65        1611 :   ulong txn_chain_cnt = fd_prog_txnm_chain_cnt_est( txn_max );
      66        1611 :   l = FD_LAYOUT_APPEND( l, fd_prog_txnm_align(), fd_prog_txnm_footprint( txn_chain_cnt ) );
      67        1611 :   l = FD_LAYOUT_APPEND( l, fd_prog_txnp_align(), fd_prog_txnp_footprint( txn_max ) );
      68             : 
      69        1611 :   ulong rec_chain_cnt = fd_prog_recm_chain_cnt_est( rec_max );
      70        1611 :   l = FD_LAYOUT_APPEND( l, fd_prog_recm_align(), fd_prog_recm_footprint( rec_chain_cnt ) );
      71        1611 :   l = FD_LAYOUT_APPEND( l, alignof(fd_progcache_rec_t), sizeof(fd_progcache_rec_t)*rec_max );
      72        1611 :   l = FD_LAYOUT_APPEND( l, fd_progcache_val_align(), arena_sz );
      73             : 
      74        1611 :   return FD_LAYOUT_FINI( l, fd_progcache_shmem_align() );
      75        1611 : }
      76             : 
      77             : /* fd_progcache_setup_slots provisions progcache_sz across the classes.  Returns rec_max (== sum(slot_cnt)),
      78             :    or 0 if the budget cannot cover class_min for every class. */
      79             : 
      80             : ulong
      81             : fd_progcache_setup_slots( ulong   txn_max,
      82             :                           ulong   progcache_sz,
      83        1122 :                           ulong * slot_cnt ) {
      84             :   /* Share of the surplus per data class, from the mainnet size distribution.
      85             :      Class 0 is not distributed by share: it takes the remainder, so its entry
      86             :      below is nominal and it also absorbs every other class's rounding slack. */
      87        1122 :   static const uint pct[ FD_PROGCACHE_CACHE_CLASS_CNT ] = {
      88        1122 :      4U,   /* class 0: 128 KiB */
      89        1122 :     29U,   /* class 1: 512 KiB */
      90        1122 :     25U,   /* class 2:   1 MiB */
      91        1122 :     18U,   /* class 3:   2 MiB */
      92        1122 :     14U,   /* class 4:   4 MiB */
      93        1122 :     10U,   /* class 5:  ~10 MiB */
      94        1122 :   };
      95             : 
      96        1122 :   ulong min_sz = fd_progcache_shmem_min_sz( txn_max );
      97        1122 :   if( FD_UNLIKELY( progcache_sz<min_sz ) ) return 0UL;
      98             : 
      99             :   /* Seed every class with its guaranteed minimum, which is what min_sz paid for. */
     100        3864 :   for( ulong c=0UL; c<FD_PROGCACHE_CACHE_CLASS_CNT; c++ ) {
     101        3312 :     slot_cnt[ c ] = fd_progcache_cache_class_min( c );
     102        3312 :   }
     103             : 
     104             :   /* Distribute the surplus by percentage, rounding down. */
     105         552 :   ulong surplus  = progcache_sz - min_sz;
     106         552 :   ulong leftover = surplus;
     107        3312 :   for( ulong c=1UL; c<FD_PROGCACHE_CACHE_CLASS_CNT; c++ ) {
     108        2760 :     ulong want = ((surplus/100UL)*(ulong)pct[ c ]) / fd_progcache_slot_cost( c );
     109        2760 :     slot_cnt[ c ] += want;
     110        2760 :     leftover      -= want*fd_progcache_slot_cost( c );
     111        2760 :   }
     112         552 :   slot_cnt[ 0 ] += leftover / fd_progcache_slot_cost( 0 );
     113             : 
     114         552 :   ulong rec_max = 0UL;
     115        3864 :   for( ulong c=0UL; c<FD_PROGCACHE_CACHE_CLASS_CNT; c++ ) rec_max += slot_cnt[ c ];
     116         552 :   return rec_max;
     117        1122 : }
     118             : 
     119             : FD_FN_CONST ulong
     120        4587 : fd_progcache_shmem_align( void ) {
     121        4587 :   return fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max( fd_ulong_max(
     122        4587 :       alignof(fd_progcache_shmem_t),
     123        4587 :       fd_prog_txnm_align() ),
     124        4587 :       fd_prog_txnp_align() ),
     125        4587 :       alignof(fd_progcache_txn_t) ),
     126        4587 :       fd_prog_recm_align() ),
     127        4587 :       alignof(fd_progcache_rec_t) ),
     128        4587 :       fd_progcache_val_align() );
     129        4587 : }
     130             : 
     131             : /* Fork depth cannot exceed txn_max, so bounding txn_max by the lineage array's
     132             :    depth is what keeps fd_progcache_load_fork from overrunning it. */
     133             : 
     134             : ulong
     135        1410 : fd_progcache_shmem_min_sz( ulong txn_max ) {
     136        1410 :   if( FD_UNLIKELY( !txn_max || txn_max>FD_PROGCACHE_DEPTH_MAX ) ) return 0UL;
     137             : 
     138        1407 :   ulong min_sz = fd_progcache_layout_footprint( txn_max, 0UL, 0UL ) + fd_progcache_val_align();
     139        9849 :   for( ulong c=0UL; c<FD_PROGCACHE_CACHE_CLASS_CNT; c++ ) {
     140        8442 :     min_sz += fd_progcache_cache_class_min( c )*fd_progcache_slot_cost( c );
     141        8442 :   }
     142             : 
     143             :   /* round at 1MiB */
     144        1407 :   return ( (min_sz>>20UL)+1UL )<<20UL;
     145        1410 : }
     146             : 
     147             : ulong
     148             : fd_progcache_shmem_footprint( ulong txn_max,
     149         897 :                               ulong progcache_sz ) {
     150         897 :   if( FD_UNLIKELY( !txn_max || txn_max>FD_PROGCACHE_DEPTH_MAX ) ) return 0UL;
     151             : 
     152             :   /* explicitly validate that progcache_sz is enough */
     153         897 :   ulong slot_cnt[ FD_PROGCACHE_CACHE_CLASS_CNT ];
     154         897 :   if( FD_UNLIKELY( !fd_progcache_setup_slots( txn_max, progcache_sz, slot_cnt ) ) ) return 0UL;
     155             : 
     156         333 :   return progcache_sz;
     157         897 : }
     158             : 
     159             : fd_progcache_shmem_t *
     160             : fd_progcache_shmem_new( void * shmem,
     161             :                         ulong  wksp_tag,
     162             :                         ulong  seed,
     163             :                         ulong  txn_max,
     164         213 :                         ulong  progcache_sz ) {
     165         213 :   fd_progcache_shmem_t * pc   = shmem;
     166         213 :   fd_wksp_t *            wksp = fd_wksp_containing( shmem );
     167             : 
     168         213 :   if( FD_UNLIKELY( !pc ) ) {
     169           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     170           0 :     return NULL;
     171           0 :   }
     172             : 
     173         213 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)pc, fd_progcache_shmem_align() ) ) ) {
     174           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
     175           0 :     return NULL;
     176           0 :   }
     177             : 
     178         213 :   if( FD_UNLIKELY( !wksp_tag ) ) {
     179           0 :     FD_LOG_WARNING(( "bad wksp_tag" ));
     180           0 :     return NULL;
     181           0 :   }
     182             : 
     183         213 :   if( FD_UNLIKELY( !wksp ) ) {
     184           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     185           0 :     return NULL;
     186           0 :   }
     187             : 
     188         213 :   if( FD_UNLIKELY( !txn_max || txn_max>FD_PROGCACHE_DEPTH_MAX ) ) {
     189           6 :     FD_LOG_WARNING(( "invalid txn_max" ));
     190           6 :     return NULL;
     191           6 :   }
     192             : 
     193         207 :   ulong slot_cnt[ FD_PROGCACHE_CACHE_CLASS_CNT ];
     194         207 :   ulong rec_max = fd_progcache_setup_slots( txn_max, progcache_sz, slot_cnt );
     195         207 :   if( FD_UNLIKELY( !rec_max || rec_max>UINT_MAX ) ) {
     196           3 :     FD_LOG_WARNING(( "invalid progcache_sz (%lu B)", progcache_sz ));
     197           3 :     return NULL;
     198           3 :   }
     199         204 :   ulong arena_sz = fd_progcache_arena_sz( slot_cnt );
     200             : 
     201         204 :   FD_SCRATCH_ALLOC_INIT( l, pc+1 );
     202             : 
     203         204 :   ulong txn_chain_cnt = fd_prog_txnm_chain_cnt_est( txn_max );
     204         204 :   void * txn_map  = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_txnm_align(), fd_prog_txnm_footprint( txn_chain_cnt ) );
     205         204 :   void * txn_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_txnp_align(), fd_prog_txnp_footprint( txn_max ) );
     206             : 
     207         204 :   ulong rec_chain_cnt = fd_prog_recm_chain_cnt_est( rec_max );
     208         204 :   void *               rec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_prog_recm_align(), fd_prog_recm_footprint( rec_chain_cnt ) );
     209         204 :   fd_progcache_rec_t * rec_ele = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_progcache_rec_t), sizeof(fd_progcache_rec_t)*rec_max );
     210         204 :   uchar *              arena   = FD_SCRATCH_ALLOC_APPEND( l, fd_progcache_val_align(), arena_sz );
     211             : 
     212         204 :   ulong layout_sz = fd_progcache_layout_footprint( txn_max, rec_max, arena_sz );
     213         204 :   FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_progcache_shmem_align() ) == (ulong)pc + layout_sz );
     214         204 :   FD_TEST( layout_sz<=progcache_sz );
     215             : 
     216         204 :   fd_memset( pc,         0, offsetof(fd_progcache_shmem_t, spill) ); /* spill fields set below */
     217         204 :   fd_memset( &pc->cache, 0, sizeof(pc->cache)                     );
     218         204 :   fd_memset( rec_ele,    0, rec_max*sizeof(fd_progcache_rec_t)    );
     219             : 
     220         204 :   pc->wksp_tag = wksp_tag;
     221         204 :   pc->seed     = seed;
     222             : 
     223             :   /* Fork graph */
     224             : 
     225         204 :   pc->txn.map_gaddr = fd_wksp_gaddr_fast( wksp, fd_prog_txnm_new( txn_map, txn_chain_cnt, seed ) );
     226         204 :   void * txn_pool2 = fd_prog_txnp_new( txn_pool, txn_max );
     227         204 :   pc->txn.pool_gaddr = fd_wksp_gaddr_fast( wksp, txn_pool2 );
     228         204 :   fd_progcache_txn_t * txn_ele = fd_prog_txnp_join( txn_pool2 );
     229         204 :   pc->txn.ele_gaddr = fd_wksp_gaddr_fast( wksp, txn_ele );
     230         204 :   pc->txn.max = txn_max;
     231         204 :   pc->txn.child_head_idx = UINT_MAX;
     232         204 :   pc->txn.child_tail_idx = UINT_MAX;
     233         204 :   pc->txn.root = fd_progcache_fork_id_initial();
     234         204 :   pc->txn.seq  = fd_progcache_fork_id_initial();
     235         204 :   fd_rwlock_new( &pc->txn.rwlock );
     236        3900 :   for( ulong i=0UL; i<txn_max; i++ ) {
     237        3696 :     fd_rwlock_new( &txn_ele[ i ].lock );
     238        3696 :   }
     239         204 :   fd_prog_txnp_leave( txn_ele );
     240             : 
     241             :   /* Record map + array.  Records double as value slots: free records are
     242             :      kept write-locked (a stale speculative reader can never lock one) on
     243             :      their class's free list. */
     244             : 
     245         204 :   pc->rec.map_gaddr   = fd_wksp_gaddr_fast( wksp, fd_prog_recm_new( rec_map, rec_chain_cnt, seed ) );
     246         204 :   pc->rec.ele_gaddr   = fd_wksp_gaddr_fast( wksp, rec_ele );
     247         204 :   pc->rec.max         = (uint)rec_max;
     248       41526 :   for( ulong i=0UL; i<rec_max; i++ ) rec_ele[ i ].lock.value = FD_RWLOCK_WRITE_LOCK;
     249             : 
     250         204 :   fd_rwlock_new( &pc->spill.lock );
     251         204 :   pc->spill.rec_used  = 0U;
     252         204 :   pc->spill.spad_used = 0U;
     253             : 
     254             :   /* Size-class cache: partition the record array and the value arena by class. */
     255         204 :   ulong rec_base    = 0UL;
     256         204 :   ulong arena_gaddr = arena_sz ? fd_wksp_gaddr_fast( wksp, arena ) : 0UL;
     257             : 
     258         204 :   ulong arena_off = 0UL;
     259        1428 :   for( ulong c=0UL; c<FD_PROGCACHE_CACHE_CLASS_CNT; c++ ) {
     260        1224 :     ulong n       = slot_cnt[ c ];
     261        1224 :     ulong slot_sz = fd_progcache_cache_slot_sz[ c ];
     262        1224 :     pc->cache.class_max     [ c ] = n;
     263        1224 :     pc->cache.rec_base  [ c ] = rec_base;
     264        1224 :     pc->cache.clock_hand[ c ].val = 0UL; /* ticket, not an index */
     265             : 
     266             :     /* Every record starts free.  Construction is single threaded, so chain them
     267             :        directly: the top is the highest index and each links to the one below, so
     268             :        a class hands out descending indices.  An empty class parks UINT_MAX. */
     269        1224 :     pc->cache.free_cnt[ c ].val     = n;
     270        1224 :     pc->cache.free_top[ c ].ver_top = n ? (ulong)(uint)( rec_base+n-1UL ) : (ulong)UINT_MAX;
     271       42546 :     for( ulong s=0UL; s<n; s++ )
     272       41322 :       rec_ele[ rec_base+s ].free_next = (uint)( s ? ( rec_base+s-1UL ) : (ulong)UINT_MAX );
     273             : 
     274        1224 :     if( n ) {
     275        1224 :       pc->cache.arena_gaddr[ c ] = arena_gaddr + arena_off;
     276        1224 :       arena_off += n*slot_sz;
     277        1224 :     }
     278             : 
     279        1224 :     rec_base += n;
     280        1224 :   }
     281             : 
     282         204 :   FD_COMPILER_MFENCE();
     283         204 :   FD_VOLATILE( pc->magic ) = FD_PROGCACHE_SHMEM_MAGIC;
     284         204 :   FD_COMPILER_MFENCE();
     285             : 
     286         204 :   return (void *)pc;
     287             : 
     288         204 : }
     289             : 
     290             : fd_progcache_join_t *
     291             : fd_progcache_shmem_join( fd_progcache_join_t *  ljoin,
     292         246 :                          fd_progcache_shmem_t * shmem ) {
     293             : 
     294         246 :   if( FD_UNLIKELY( !shmem ) ) {
     295           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     296           0 :     return NULL;
     297           0 :   }
     298         246 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
     299           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
     300           0 :     return NULL;
     301           0 :   }
     302         246 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
     303         246 :   if( FD_UNLIKELY( !wksp ) ) {
     304           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     305           0 :     return NULL;
     306           0 :   }
     307         246 :   if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
     308           0 :     FD_LOG_WARNING(( "bad magic" ));
     309           0 :     return NULL;
     310           0 :   }
     311             : 
     312         246 :   if( FD_UNLIKELY( !ljoin ) ) {
     313           0 :     FD_LOG_WARNING(( "NULL join" ));
     314           0 :     return NULL;
     315           0 :   }
     316             : 
     317         246 :   memset( ljoin, 0, sizeof(fd_progcache_join_t) );
     318             : 
     319         246 :   ljoin->shmem     = shmem;
     320         246 :   ljoin->data_base = wksp; /* all value/bookkeeping gaddrs are wksp-relative */
     321             : 
     322         246 :   ljoin->txn.map = fd_prog_txnm_join( fd_wksp_laddr( wksp, shmem->txn.map_gaddr ) );
     323         246 :   if( FD_UNLIKELY( !ljoin->txn.map ) ) {
     324           0 :     FD_LOG_WARNING(( "fd_prog_txnm_join failed" ));
     325           0 :     return NULL;
     326           0 :   }
     327         246 :   ljoin->txn.pool = fd_prog_txnp_join( fd_wksp_laddr( wksp, shmem->txn.pool_gaddr ) );
     328         246 :   if( FD_UNLIKELY( !ljoin->txn.pool ) ) {
     329           0 :     FD_LOG_WARNING(( "fd_prog_txnp_join failed" ));
     330           0 :     return NULL;
     331           0 :   }
     332         246 :   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 ) ) ) {
     333           0 :     FD_LOG_WARNING(( "fd_prog_recm_join failed" ));
     334           0 :     return NULL;
     335           0 :   }
     336         246 :   ljoin->rec.ele = fd_wksp_laddr( wksp, shmem->rec.ele_gaddr );
     337         246 :   ljoin->rec.max = shmem->rec.max;
     338             : 
     339         246 :   return ljoin;
     340         246 : }
     341             : 
     342             : void *
     343             : fd_progcache_shmem_leave( fd_progcache_join_t *   ljoin,
     344         246 :                           fd_progcache_shmem_t ** opt_shmem ) {
     345             : 
     346         246 :   if( FD_UNLIKELY( !ljoin ) ) {
     347           0 :     FD_LOG_WARNING(( "NULL join" ));
     348           0 :     if( opt_shmem ) *opt_shmem = NULL;
     349           0 :     return NULL;
     350           0 :   }
     351             : 
     352         246 :   void * shmem = ljoin->shmem;
     353             : 
     354         246 :   memset( ljoin, 0, sizeof(fd_progcache_join_t) );
     355             : 
     356         246 :   if( opt_shmem ) *opt_shmem = shmem;
     357         246 :   return shmem;
     358         246 : }
     359             : 
     360             : void *
     361         201 : fd_progcache_shmem_delete( fd_progcache_shmem_t * shmem ) {
     362             : 
     363         201 :   if( FD_UNLIKELY( !shmem ) ) {
     364           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     365           0 :     return NULL;
     366           0 :   }
     367             : 
     368         201 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
     369           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
     370           0 :     return NULL;
     371           0 :   }
     372             : 
     373         201 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
     374         201 :   if( FD_UNLIKELY( !wksp ) ) {
     375           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     376           0 :     return NULL;
     377           0 :   }
     378             : 
     379         201 :   if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
     380           0 :     FD_LOG_WARNING(( "bad magic" ));
     381           0 :     return NULL;
     382           0 :   }
     383             : 
     384         201 :   FD_TEST( !shmem->txn.rwlock.value );
     385         201 :   fd_progcache_txn_t * txn0 = fd_wksp_laddr_fast( wksp, shmem->txn.ele_gaddr );
     386        3849 :   for( ulong i=0UL; i<shmem->txn.max; i++ ) FD_TEST( !txn0[ i ].lock.value );
     387         201 :   FD_TEST( !shmem->spill.lock.value );
     388             : 
     389         201 :   FD_COMPILER_MFENCE();
     390         201 :   FD_VOLATILE( shmem->magic ) = 0UL;
     391         201 :   FD_COMPILER_MFENCE();
     392             : 
     393         201 :   return shmem;
     394         201 : }
     395             : 
     396             : void *
     397           3 : fd_progcache_shmem_delete_fast( fd_progcache_shmem_t * shmem ) {
     398             : 
     399           3 :   if( FD_UNLIKELY( !shmem ) ) {
     400           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     401           0 :     return NULL;
     402           0 :   }
     403             : 
     404           3 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_progcache_shmem_align() ) ) ) {
     405           0 :     FD_LOG_WARNING(( "misaligned shmem" ));
     406           0 :     return NULL;
     407           0 :   }
     408             : 
     409           3 :   if( FD_UNLIKELY( !fd_wksp_containing( shmem ) ) ) {
     410           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
     411           0 :     return NULL;
     412           0 :   }
     413             : 
     414           3 :   if( FD_UNLIKELY( shmem->magic!=FD_PROGCACHE_SHMEM_MAGIC ) ) {
     415           0 :     FD_LOG_WARNING(( "bad magic" ));
     416           0 :     return NULL;
     417           0 :   }
     418             : 
     419           3 :   FD_COMPILER_MFENCE();
     420           3 :   FD_VOLATILE( shmem->magic ) = 0UL;
     421           3 :   FD_COMPILER_MFENCE();
     422             : 
     423           3 :   fd_wksp_free_laddr( shmem );
     424             : 
     425           3 :   return shmem;
     426           3 : }

Generated by: LCOV version 1.14