LCOV - code coverage report
Current view: top level - funkier - fd_funkier.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 82 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #include "fd_funkier.h"
       2             : #include <stdio.h>
       3             : 
       4             : ulong
       5           0 : fd_funkier_align( void ) {
       6           0 :   return FD_FUNKIER_ALIGN;
       7           0 : }
       8             : 
       9             : ulong
      10             : fd_funkier_footprint( ulong txn_max,
      11           0 :                       ulong rec_max ) {
      12             : 
      13           0 :   ulong l = FD_LAYOUT_INIT;
      14             : 
      15           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funkier_t), sizeof(fd_funkier_t) );
      16             : 
      17           0 :   ulong txn_chain_cnt = fd_funkier_txn_map_chain_cnt_est( txn_max );
      18           0 :   l = FD_LAYOUT_APPEND( l, fd_funkier_txn_map_align(), fd_funkier_txn_map_footprint( txn_chain_cnt ) );
      19           0 :   l = FD_LAYOUT_APPEND( l, fd_funkier_txn_pool_align(), fd_funkier_txn_pool_footprint() );
      20           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funkier_txn_t), sizeof(fd_funkier_txn_t) * txn_max );
      21             : 
      22           0 :   ulong rec_chain_cnt = fd_funkier_rec_map_chain_cnt_est( rec_max );
      23           0 :   l = FD_LAYOUT_APPEND( l, fd_funkier_rec_map_align(), fd_funkier_rec_map_footprint( rec_chain_cnt ) );
      24           0 :   l = FD_LAYOUT_APPEND( l, fd_funkier_rec_pool_align(), fd_funkier_rec_pool_footprint() );
      25           0 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funkier_rec_t), sizeof(fd_funkier_rec_t) * rec_max );
      26             : 
      27           0 :   l = FD_LAYOUT_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      28             : 
      29           0 :   return l;
      30           0 : }
      31             : 
      32             : /* TODO: Consider letter user just passing a join of alloc to use,
      33             :    inferring the backing wksp and cgroup_hint from that and then
      34             :    allocating exclusively from that? */
      35             : 
      36             : void *
      37             : fd_funkier_new( void * shmem,
      38             :                 ulong  wksp_tag,
      39             :                 ulong  seed,
      40             :                 ulong  txn_max,
      41           0 :                 ulong  rec_max ) {
      42           0 :   fd_funkier_t * funk = (fd_funkier_t *)shmem;
      43           0 :   fd_wksp_t * wksp = fd_wksp_containing( funk );
      44             : 
      45             : #ifdef FD_FUNKIER_HANDHOLDING
      46             :   if( FD_UNLIKELY( !funk ) ) {
      47             :     FD_LOG_WARNING(( "NULL funk" ));
      48             :     return NULL;
      49             :   }
      50             : 
      51             :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funkier_align() ) ) ) {
      52             :     FD_LOG_WARNING(( "misaligned funk" ));
      53             :     return NULL;
      54             :   }
      55             : 
      56             :   if( FD_UNLIKELY( !wksp_tag ) ) {
      57             :     FD_LOG_WARNING(( "bad wksp_tag" ));
      58             :     return NULL;
      59             :   }
      60             : 
      61             :   if( FD_UNLIKELY( !wksp ) ) {
      62             :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
      63             :     return NULL;
      64             :   }
      65             : 
      66             :   if( txn_max>FD_FUNKIER_TXN_IDX_NULL ) { /* See note in fd_funkier.h about this limit */
      67             :     FD_LOG_WARNING(( "txn_max too large for index compression" ));
      68             :     return NULL;
      69             :   }
      70             : #endif
      71             : 
      72           0 :   FD_SCRATCH_ALLOC_INIT( l, funk+1 );
      73             : 
      74           0 :   ulong txn_chain_cnt = fd_funkier_txn_map_chain_cnt_est( txn_max );
      75           0 :   void * txn_map = FD_SCRATCH_ALLOC_APPEND( l, fd_funkier_txn_map_align(), fd_funkier_txn_map_footprint( txn_chain_cnt ) );
      76           0 :   void * txn_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_funkier_txn_pool_align(), fd_funkier_txn_pool_footprint() );
      77           0 :   fd_funkier_txn_t * txn_ele = (fd_funkier_txn_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_funkier_txn_t), sizeof(fd_funkier_txn_t) * txn_max );
      78             : 
      79           0 :   ulong rec_chain_cnt = fd_funkier_rec_map_chain_cnt_est( rec_max );
      80           0 :   void * rec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_funkier_rec_map_align(), fd_funkier_rec_map_footprint( rec_chain_cnt ) );
      81           0 :   void * rec_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_funkier_rec_pool_align(), fd_funkier_rec_pool_footprint() );
      82           0 :   fd_funkier_rec_t * rec_ele = (fd_funkier_rec_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_funkier_rec_t), sizeof(fd_funkier_rec_t) * rec_max );
      83             : 
      84           0 :   void * alloc = FD_SCRATCH_ALLOC_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      85             : 
      86           0 :   FD_TEST( _l == (ulong)funk + fd_funkier_footprint( txn_max, rec_max ) );
      87             : 
      88           0 :   fd_memset( funk, 0, sizeof(fd_funkier_t) );
      89             : 
      90           0 :   funk->funk_gaddr = fd_wksp_gaddr_fast( wksp, funk );
      91           0 :   funk->wksp_tag   = wksp_tag;
      92           0 :   funk->seed       = seed;
      93           0 :   funk->cycle_tag  = 3UL; /* various verify functions use tags 0-2 */
      94             : 
      95           0 :   funk->txn_map_gaddr = fd_wksp_gaddr_fast( wksp, fd_funkier_txn_map_new( txn_map, txn_chain_cnt, seed ) );
      96           0 :   void * txn_pool2 = fd_funkier_txn_pool_new( txn_pool );
      97           0 :   funk->txn_pool_gaddr = fd_wksp_gaddr_fast( wksp, txn_pool2 );
      98           0 :   fd_funkier_txn_pool_t txn_join[1];
      99           0 :   fd_funkier_txn_pool_join( txn_join, txn_pool2, txn_ele, txn_max );
     100           0 :   fd_funkier_txn_pool_reset( txn_join, 0UL );
     101           0 :   funk->txn_ele_gaddr = fd_wksp_gaddr_fast( wksp, txn_ele );
     102           0 :   funk->txn_max = txn_max;
     103           0 :   funk->child_head_cidx = fd_funkier_txn_cidx( FD_FUNKIER_TXN_IDX_NULL );
     104           0 :   funk->child_tail_cidx = fd_funkier_txn_cidx( FD_FUNKIER_TXN_IDX_NULL );
     105             : 
     106           0 :   fd_funkier_txn_xid_set_root( funk->root         );
     107           0 :   fd_funkier_txn_xid_set_root( funk->last_publish );
     108             : 
     109           0 :   funk->rec_map_gaddr = fd_wksp_gaddr_fast( wksp, fd_funkier_rec_map_new( rec_map, rec_chain_cnt, seed ) );
     110           0 :   void * rec_pool2 = fd_funkier_rec_pool_new( rec_pool );
     111           0 :   funk->rec_pool_gaddr = fd_wksp_gaddr_fast( wksp, rec_pool2 );
     112           0 :   fd_funkier_rec_pool_t rec_join[1];
     113           0 :   fd_funkier_rec_pool_join( rec_join, rec_pool2, rec_ele, rec_max );
     114           0 :   fd_funkier_rec_pool_reset( rec_join, 0UL );
     115           0 :   funk->rec_ele_gaddr = fd_wksp_gaddr_fast( wksp, rec_ele );
     116           0 :   funk->rec_max = rec_max;
     117           0 :   funk->rec_head_idx  = FD_FUNKIER_REC_IDX_NULL;
     118           0 :   funk->rec_tail_idx  = FD_FUNKIER_REC_IDX_NULL;
     119             : 
     120           0 :   funk->alloc_gaddr = fd_wksp_gaddr_fast( wksp, fd_alloc_join( fd_alloc_new( alloc, wksp_tag ), 0UL ) );
     121             : 
     122           0 :   FD_COMPILER_MFENCE();
     123           0 :   FD_VOLATILE( funk->magic ) = FD_FUNKIER_MAGIC;
     124           0 :   FD_COMPILER_MFENCE();
     125             : 
     126           0 :   return (void *)funk;
     127           0 : }
     128             : 
     129             : fd_funkier_t *
     130           0 : fd_funkier_join( void * shfunk ) {
     131           0 :   fd_funkier_t * funk = (fd_funkier_t *)shfunk;
     132             : 
     133             : #ifdef FD_FUNKIER_HANDHOLDING
     134             :   if( FD_UNLIKELY( !funk ) ) {
     135             :     FD_LOG_WARNING(( "NULL shfunk" ));
     136             :     return NULL;
     137             :   }
     138             : 
     139             :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funkier_align() ) ) ) {
     140             :     FD_LOG_WARNING(( "misaligned shfunk" ));
     141             :     return NULL;
     142             :   }
     143             : 
     144             :   fd_wksp_t * wksp = fd_wksp_containing( funk );
     145             :   if( FD_UNLIKELY( !wksp ) ) {
     146             :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     147             :     return NULL;
     148             :   }
     149             : 
     150             :   if( FD_UNLIKELY( funk->magic!=FD_FUNKIER_MAGIC ) ) {
     151             :     FD_LOG_WARNING(( "bad magic" ));
     152             :     return NULL;
     153             :   }
     154             : #endif
     155             : 
     156             : #ifdef FD_FUNKIER_WKSP_PROTECT
     157             : #ifndef FD_FUNKIER_HANDHOLDING
     158             :   fd_wksp_t * wksp = fd_wksp_containing( funk );
     159             : #endif
     160             :   fd_wksp_mprotect( wksp, 1 );
     161             : #endif
     162             : 
     163           0 :   return funk;
     164           0 : }
     165             : 
     166             : void *
     167           0 : fd_funkier_leave( fd_funkier_t * funk ) {
     168             : 
     169           0 :   if( FD_UNLIKELY( !funk ) ) {
     170           0 :     FD_LOG_WARNING(( "NULL funk" ));
     171           0 :     return NULL;
     172           0 :   }
     173             : 
     174           0 :   return (void *)funk;
     175           0 : }
     176             : 
     177             : void *
     178           0 : fd_funkier_delete( void * shfunk ) {
     179           0 :   fd_funkier_t * funk = (fd_funkier_t *)shfunk;
     180             : 
     181             : #ifdef FD_FUNKIER_HANDHOLDING
     182             :   if( FD_UNLIKELY( !funk ) ) {
     183             :     FD_LOG_WARNING(( "NULL shfunk" ));
     184             :     return NULL;
     185             :   }
     186             : 
     187             :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funkier_align() ) ) ) {
     188             :     FD_LOG_WARNING(( "misaligned shfunk" ));
     189             :     return NULL;
     190             :   }
     191             : 
     192             :   fd_wksp_t * wksp = fd_wksp_containing( funk );
     193             :   if( FD_UNLIKELY( !wksp ) ) {
     194             :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     195             :     return NULL;
     196             :   }
     197             : 
     198             :   if( FD_UNLIKELY( funk->magic!=FD_FUNKIER_MAGIC ) ) {
     199             :     FD_LOG_WARNING(( "bad magic" ));
     200             :     return NULL;
     201             :   }
     202             : #endif
     203             : 
     204           0 :   FD_COMPILER_MFENCE();
     205           0 :   FD_VOLATILE( funk->magic ) = 0UL;
     206           0 :   FD_COMPILER_MFENCE();
     207             : 
     208           0 :   return funk;
     209           0 : }
     210             : 
     211             : #ifdef FD_FUNKIER_HANDHOLDING
     212             : int
     213             : fd_funkier_verify( fd_funkier_t * funk ) {
     214             : 
     215             : # define TEST(c) do {                                                                           \
     216             :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNKIER_ERR_INVAL; } \
     217             :   } while(0)
     218             : 
     219             :   TEST( funk );
     220             : 
     221             :   /* Test metadata */
     222             : 
     223             :   TEST( funk->magic==FD_FUNKIER_MAGIC );
     224             : 
     225             :   ulong funk_gaddr = funk->funk_gaddr;
     226             :   TEST( funk_gaddr );
     227             :   fd_wksp_t * wksp = fd_funkier_wksp( funk );
     228             :   TEST( wksp );
     229             :   TEST( fd_wksp_laddr_fast( wksp, funk_gaddr )==(void *)funk );
     230             :   TEST( fd_wksp_gaddr_fast( wksp, funk       )==funk_gaddr   );
     231             : 
     232             :   ulong wksp_tag = fd_funkier_wksp_tag( funk );
     233             :   TEST( !!wksp_tag );
     234             : 
     235             :   ulong seed = funk->seed; /* seed can be anything */
     236             : 
     237             :   TEST( funk->cycle_tag>2UL );
     238             : 
     239             :   /* Test transaction map */
     240             : 
     241             :   ulong txn_max = funk->txn_max;
     242             :   TEST( txn_max<=FD_FUNKIER_TXN_IDX_NULL );
     243             : 
     244             :   ulong txn_map_gaddr = funk->txn_map_gaddr;
     245             :   TEST( txn_map_gaddr );
     246             :   fd_funkier_txn_map_t txn_map = fd_funkier_txn_map( funk, wksp );
     247             :   ulong txn_chain_cnt = fd_funkier_txn_map_chain_cnt_est( txn_max );
     248             :   TEST( txn_chain_cnt==fd_funkier_txn_map_chain_cnt( &txn_map ) );
     249             :   TEST( seed==fd_funkier_txn_map_seed( &txn_map ) );
     250             : 
     251             :   ulong child_head_idx = fd_funkier_txn_idx( funk->child_head_cidx );
     252             :   ulong child_tail_idx = fd_funkier_txn_idx( funk->child_tail_cidx );
     253             : 
     254             :   int null_child_head = fd_funkier_txn_idx_is_null( child_head_idx );
     255             :   int null_child_tail = fd_funkier_txn_idx_is_null( child_tail_idx );
     256             : 
     257             :   if( !txn_max ) TEST( null_child_head & null_child_tail );
     258             :   else {
     259             :     if( null_child_head ) TEST( null_child_tail );
     260             :     else                  TEST( child_head_idx<txn_max );
     261             : 
     262             :     if( null_child_tail ) TEST( null_child_head );
     263             :     else                  TEST( child_tail_idx<txn_max );
     264             :   }
     265             : 
     266             :   if( !txn_max ) TEST( fd_funkier_txn_idx_is_null( child_tail_idx ) );
     267             : 
     268             :   fd_funkier_txn_xid_t const * root = fd_funkier_root( funk );
     269             :   TEST( root ); /* Practically guaranteed */
     270             :   TEST( fd_funkier_txn_xid_eq_root( root ) );
     271             : 
     272             :   fd_funkier_txn_xid_t * last_publish = funk->last_publish;
     273             :   TEST( last_publish ); /* Practically guaranteed */
     274             :   /* (*last_publish) only be root at creation and anything but root post
     275             :      creation.  But we don't know which situation applies here so this
     276             :      could be anything. */
     277             : 
     278             :   TEST( !fd_funkier_txn_verify( funk ) );
     279             : 
     280             :   /* Test record map */
     281             : 
     282             :   ulong rec_max = funk->rec_max;
     283             :   TEST( rec_max<=FD_FUNKIER_TXN_IDX_NULL );
     284             : 
     285             :   ulong rec_map_gaddr = funk->rec_map_gaddr;
     286             :   TEST( rec_map_gaddr );
     287             :   fd_funkier_rec_map_t rec_map = fd_funkier_rec_map( funk, wksp );
     288             :   ulong rec_chain_cnt = fd_funkier_rec_map_chain_cnt_est( rec_max );
     289             :   TEST( rec_chain_cnt==fd_funkier_rec_map_chain_cnt( &rec_map ) );
     290             :   TEST( seed==fd_funkier_rec_map_seed( &rec_map ) );
     291             : 
     292             :   ulong rec_head_idx = funk->rec_head_idx;
     293             :   ulong rec_tail_idx = funk->rec_tail_idx;
     294             : 
     295             :   int null_rec_head = fd_funkier_rec_idx_is_null( rec_head_idx );
     296             :   int null_rec_tail = fd_funkier_rec_idx_is_null( rec_tail_idx );
     297             : 
     298             :   if( !rec_max ) TEST( null_rec_head & null_rec_tail );
     299             :   else {
     300             :     if( null_rec_head ) TEST( null_rec_tail );
     301             :     else                TEST( rec_head_idx<rec_max );
     302             : 
     303             :     if( null_rec_tail ) TEST( null_rec_head );
     304             :     else                TEST( rec_tail_idx<rec_max );
     305             :   }
     306             : 
     307             :   if( !rec_max ) TEST( fd_funkier_rec_idx_is_null( rec_tail_idx ) );
     308             : 
     309             :   TEST( !fd_funkier_rec_verify( funk ) );
     310             : 
     311             :   /* Test values */
     312             : 
     313             :   ulong alloc_gaddr = funk->alloc_gaddr;
     314             :   TEST( alloc_gaddr );
     315             :   fd_alloc_t * alloc = fd_funkier_alloc( funk, wksp );
     316             :   TEST( alloc );
     317             : 
     318             :   TEST( !fd_funkier_val_verify( funk ) );
     319             : 
     320             : # undef TEST
     321             : 
     322             :   return FD_FUNKIER_SUCCESS;
     323             : }
     324             : #endif

Generated by: LCOV version 1.14