LCOV - code coverage report
Current view: top level - funk - fd_funk.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 234 337 69.4 %
Date: 2024-11-13 11:58:15 Functions: 10 13 76.9 %

          Line data    Source code
       1             : #include "fd_funk.h"
       2             : #include <stdio.h>
       3             : 
       4             : ulong
       5      220794 : fd_funk_align( void ) {
       6      220794 :   return alignof(fd_funk_t);
       7      220794 : }
       8             : 
       9             : ulong
      10      220794 : fd_funk_footprint( void ) {
      11      220794 :   return sizeof(fd_funk_t);
      12      220794 : }
      13             : 
      14             : /* TODO: Consider letter user just passing a join of alloc to use,
      15             :    inferring the backing wksp and cgroup_hint from that and then
      16             :    allocating exclusively from that? */
      17             : 
      18             : void *
      19             : fd_funk_new( void * shmem,
      20             :              ulong  wksp_tag,
      21             :              ulong  seed,
      22             :              ulong  txn_max,
      23      110589 :              ulong  rec_max ) {
      24      110589 :   fd_funk_t * funk = (fd_funk_t *)shmem;
      25             : 
      26      110589 :   if( FD_UNLIKELY( !funk ) ) {
      27           3 :     FD_LOG_WARNING(( "NULL funk" ));
      28           3 :     return NULL;
      29           3 :   }
      30             : 
      31      110586 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funk_align() ) ) ) {
      32           3 :     FD_LOG_WARNING(( "misaligned funk" ));
      33           3 :     return NULL;
      34           3 :   }
      35             : 
      36      110583 :   if( FD_UNLIKELY( !wksp_tag ) ) {
      37           3 :     FD_LOG_WARNING(( "bad wksp_tag" ));
      38           3 :     return NULL;
      39           3 :   }
      40             : 
      41      110580 :   fd_wksp_t * wksp = fd_wksp_containing( funk );
      42      110580 :   if( FD_UNLIKELY( !wksp ) ) {
      43           3 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
      44           3 :     return NULL;
      45           3 :   }
      46             : 
      47      110577 :   if( txn_max>FD_FUNK_TXN_IDX_NULL ) { /* See note in fd_funk.h about this limit */
      48           3 :     FD_LOG_WARNING(( "txn_max too large for index compression" ));
      49           3 :     return NULL;
      50           3 :   }
      51             : 
      52      110574 :   void * txn_shmem = fd_wksp_alloc_laddr( wksp, fd_funk_txn_map_align(), fd_funk_txn_map_footprint( txn_max ), wksp_tag );
      53      110574 :   if( FD_UNLIKELY( !txn_shmem ) ) {
      54           3 :     FD_LOG_WARNING(( "txn_max too large for workspace" ));
      55           3 :     return NULL;
      56           3 :   }
      57             : 
      58      110571 :   void * txn_shmap = fd_funk_txn_map_new( txn_shmem, txn_max, seed );
      59      110571 :   if( FD_UNLIKELY( !txn_shmap ) ) {
      60           0 :     FD_LOG_WARNING(( "fd_funk_txn_map_new failed" ));
      61           0 :     fd_wksp_free_laddr( txn_shmem );
      62           0 :     return NULL;
      63           0 :   }
      64             : 
      65      110571 :   fd_funk_txn_t * txn_map = fd_funk_txn_map_join( txn_shmap );
      66      110571 :   if( FD_UNLIKELY( !txn_map ) ) {
      67           0 :     FD_LOG_WARNING(( "fd_funk_txn_map_join failed" ));
      68           0 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( txn_shmap ) );
      69           0 :     return NULL;
      70           0 :   }
      71             : 
      72      110571 :   void * rec_shmem = fd_wksp_alloc_laddr( wksp, fd_funk_rec_map_align(), fd_funk_rec_map_footprint( rec_max ), wksp_tag );
      73      110571 :   if( FD_UNLIKELY( !rec_shmem ) ) {
      74           3 :     FD_LOG_WARNING(( "rec_max too large for workspace" ));
      75           3 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( txn_map ) ) );
      76           3 :     return NULL;
      77           3 :   }
      78             : 
      79      110568 :   void * rec_shmap = fd_funk_rec_map_new( rec_shmem, rec_max, seed );
      80      110568 :   if( FD_UNLIKELY( !rec_shmap ) ) {
      81           0 :     FD_LOG_WARNING(( "fd_funk_rec_map_new failed" ));
      82           0 :     fd_wksp_free_laddr( rec_shmem );
      83           0 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( txn_map ) ) );
      84           0 :     return NULL;
      85           0 :   }
      86             : 
      87      110568 :   fd_funk_rec_t * rec_map = fd_funk_rec_map_join( rec_shmap );
      88      110568 :   if( FD_UNLIKELY( !rec_map ) ) {
      89           0 :     FD_LOG_WARNING(( "fd_funk_rec_map_join failed" ));
      90           0 :     fd_wksp_free_laddr( fd_funk_rec_map_delete( rec_shmap ) );
      91           0 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( txn_map ) ) );
      92           0 :     return NULL;
      93           0 :   }
      94             : 
      95      110568 :   void * alloc_shmem = fd_wksp_alloc_laddr( wksp, fd_alloc_align(), fd_alloc_footprint(), wksp_tag );
      96      110568 :   if( FD_UNLIKELY( !alloc_shmem ) ) {
      97           0 :     FD_LOG_WARNING(( "fd_alloc too large for workspace" ));
      98           0 :     fd_wksp_free_laddr( fd_funk_rec_map_delete( fd_funk_rec_map_leave( rec_map ) ) );
      99           0 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( txn_map ) ) );
     100           0 :     return NULL;
     101           0 :   }
     102             : 
     103      110568 :   void * alloc_shalloc = fd_alloc_new( alloc_shmem, wksp_tag );
     104      110568 :   if( FD_UNLIKELY( !alloc_shalloc ) ) {
     105           0 :     FD_LOG_WARNING(( "fd_allow_new failed" ));
     106           0 :     fd_wksp_free_laddr( alloc_shalloc );
     107           0 :     fd_wksp_free_laddr( fd_funk_rec_map_delete( fd_funk_rec_map_leave( rec_map ) ) );
     108           0 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( txn_map ) ) );
     109           0 :     return NULL;
     110           0 :   }
     111             : 
     112      110568 :   fd_alloc_t * alloc = fd_alloc_join( alloc_shalloc, 0UL ); /* TODO: Consider letting user pass the cgroup hint? */
     113      110568 :   if( FD_UNLIKELY( !alloc ) ) {
     114           0 :     FD_LOG_WARNING(( "fd_alloc_join failed" ));
     115           0 :     fd_wksp_free_laddr( fd_alloc_delete( alloc_shalloc ) );
     116           0 :     fd_wksp_free_laddr( fd_funk_rec_map_delete( fd_funk_rec_map_leave( rec_map ) ) );
     117           0 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( txn_map ) ) );
     118           0 :     return NULL;
     119           0 :   }
     120             : 
     121      110568 :   fd_memset( funk, 0, fd_funk_footprint() );
     122             : 
     123      110568 :   funk->funk_gaddr = fd_wksp_gaddr_fast( wksp, funk );
     124      110568 :   funk->wksp_tag   = wksp_tag;
     125      110568 :   funk->seed       = seed;
     126      110568 :   funk->cycle_tag  = 3UL; /* various verify functions use tags 0-2 */
     127             : 
     128      110568 :   funk->txn_max         = txn_max;
     129      110568 :   funk->txn_map_gaddr   = fd_wksp_gaddr_fast( wksp, txn_map ); /* Note that this persists the join until delete */
     130      110568 :   funk->child_head_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     131      110568 :   funk->child_tail_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     132             : 
     133      110568 :   fd_funk_txn_xid_set_root( funk->root         );
     134      110568 :   fd_funk_txn_xid_set_root( funk->last_publish );
     135             : 
     136      110568 :   funk->rec_max       = rec_max;
     137      110568 :   funk->rec_map_gaddr = fd_wksp_gaddr_fast( wksp, rec_map ); /* Note that this persists the join until delete */
     138      110568 :   funk->rec_head_idx  = FD_FUNK_REC_IDX_NULL;
     139      110568 :   funk->rec_tail_idx  = FD_FUNK_REC_IDX_NULL;
     140             : 
     141      110568 :   funk->alloc_gaddr = fd_wksp_gaddr_fast( wksp, alloc ); /* Note that this persists the join until delete */
     142             : 
     143      110568 :   ulong tmp_max;
     144      110568 :   fd_funk_partvec_t * partvec = (fd_funk_partvec_t *)fd_alloc_malloc_at_least( alloc, fd_funk_partvec_align(), fd_funk_partvec_footprint(0U), &tmp_max );
     145      110568 :   if( FD_UNLIKELY( !partvec ) ) {
     146           0 :     FD_LOG_WARNING(( "partvec alloc failed" ));
     147           0 :     fd_wksp_free_laddr( fd_alloc_delete( alloc_shalloc ) );
     148           0 :     fd_wksp_free_laddr( fd_funk_rec_map_delete( fd_funk_rec_map_leave( rec_map ) ) );
     149           0 :     fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( txn_map ) ) );
     150           0 :     return NULL;
     151           0 :   }
     152      110568 :   partvec->num_part = 0U;
     153      110568 :   funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
     154             : 
     155      110568 :   FD_COMPILER_MFENCE();
     156      110568 :   FD_VOLATILE( funk->magic ) = FD_FUNK_MAGIC;
     157      110568 :   FD_COMPILER_MFENCE();
     158             : 
     159      110568 :   return (void *)funk;
     160      110568 : }
     161             : 
     162             : fd_funk_t *
     163      110580 : fd_funk_join( void * shfunk ) {
     164      110580 :   fd_funk_t * funk = (fd_funk_t *)shfunk;
     165             : 
     166      110580 :   if( FD_UNLIKELY( !funk ) ) {
     167           3 :     FD_LOG_WARNING(( "NULL shfunk" ));
     168           3 :     return NULL;
     169           3 :   }
     170             : 
     171      110577 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funk_align() ) ) ) {
     172           3 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     173           3 :     return NULL;
     174           3 :   }
     175             : 
     176      110574 :   fd_wksp_t * wksp = fd_wksp_containing( funk );
     177      110574 :   if( FD_UNLIKELY( !wksp ) ) {
     178           3 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     179           3 :     return NULL;
     180           3 :   }
     181             : 
     182      110571 :   if( FD_UNLIKELY( funk->magic!=FD_FUNK_MAGIC ) ) {
     183           3 :     FD_LOG_WARNING(( "bad magic" ));
     184           3 :     return NULL;
     185           3 :   }
     186             : 
     187             : #ifdef FD_FUNK_WKSP_PROTECT
     188             :   fd_wksp_mprotect( wksp, 1 );
     189             : #endif
     190             : 
     191      110568 :   return funk;
     192      110571 : }
     193             : 
     194             : void *
     195      110265 : fd_funk_leave( fd_funk_t * funk ) {
     196             : 
     197      110265 :   if( FD_UNLIKELY( !funk ) ) {
     198           3 :     FD_LOG_WARNING(( "NULL funk" ));
     199           3 :     return NULL;
     200           3 :   }
     201             : 
     202      110262 :   return (void *)funk;
     203      110265 : }
     204             : 
     205             : void *
     206      110274 : fd_funk_delete( void * shfunk ) {
     207      110274 :   fd_funk_t * funk = (fd_funk_t *)shfunk;
     208             : 
     209      110274 :   if( FD_UNLIKELY( !funk ) ) {
     210           3 :     FD_LOG_WARNING(( "NULL shfunk" ));
     211           3 :     return NULL;
     212           3 :   }
     213             : 
     214      110271 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funk_align() ) ) ) {
     215           3 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     216           3 :     return NULL;
     217           3 :   }
     218             : 
     219      110268 :   fd_wksp_t * wksp = fd_wksp_containing( funk );
     220      110268 :   if( FD_UNLIKELY( !wksp ) ) {
     221           3 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     222           3 :     return NULL;
     223           3 :   }
     224             : 
     225      110265 :   if( FD_UNLIKELY( funk->magic!=FD_FUNK_MAGIC ) ) {
     226           3 :     FD_LOG_WARNING(( "bad magic" ));
     227           3 :     return NULL;
     228           3 :   }
     229             : 
     230             :   /* Free all value resources here */
     231             : 
     232      110262 :   fd_wksp_free_laddr( fd_alloc_delete       ( fd_alloc_leave       ( fd_funk_alloc  ( funk, wksp ) ) ) );
     233      110262 :   fd_wksp_free_laddr( fd_funk_rec_map_delete( fd_funk_rec_map_leave( fd_funk_rec_map( funk, wksp ) ) ) );
     234      110262 :   fd_wksp_free_laddr( fd_funk_txn_map_delete( fd_funk_txn_map_leave( fd_funk_txn_map( funk, wksp ) ) ) );
     235             : 
     236      110262 :   FD_COMPILER_MFENCE();
     237      110262 :   FD_VOLATILE( funk->magic ) = 0UL;
     238      110262 :   FD_COMPILER_MFENCE();
     239             : 
     240      110262 :   return funk;
     241      110265 : }
     242             : 
     243             : int
     244    22026408 : fd_funk_verify( fd_funk_t * funk ) {
     245             : 
     246   748897872 : # define TEST(c) do {                                                                           \
     247   748897872 :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNK_ERR_INVAL; } \
     248   748897872 :   } while(0)
     249             : 
     250    22026408 :   TEST( funk );
     251             : 
     252             :   /* Test metadata */
     253             : 
     254    22026408 :   TEST( funk->magic==FD_FUNK_MAGIC );
     255             : 
     256    22026408 :   ulong funk_gaddr = funk->funk_gaddr;
     257    22026408 :   TEST( funk_gaddr );
     258    22026408 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
     259    22026408 :   TEST( wksp );
     260    22026408 :   TEST( fd_wksp_laddr_fast( wksp, funk_gaddr )==(void *)funk );
     261    22026408 :   TEST( fd_wksp_gaddr_fast( wksp, funk       )==funk_gaddr   );
     262             : 
     263    22026408 :   ulong wksp_tag = fd_funk_wksp_tag( funk );
     264    22026408 :   TEST( !!wksp_tag );
     265             : 
     266    22026408 :   ulong seed = funk->seed; /* seed can be anything */
     267             : 
     268    22026408 :   TEST( funk->cycle_tag>2UL );
     269             : 
     270             :   /* Test transaction map */
     271             : 
     272    22026408 :   ulong txn_max = funk->txn_max;
     273    22026408 :   TEST( txn_max<=FD_FUNK_TXN_IDX_NULL );
     274             : 
     275    22026408 :   ulong txn_map_gaddr = funk->txn_map_gaddr;
     276    22026408 :   TEST( txn_map_gaddr );
     277    22026408 :   TEST( fd_wksp_tag( wksp, txn_map_gaddr-1UL )==wksp_tag ); /* When txn_max is 0, txn_map_gaddr can be first byte after alloc */
     278    22026408 :   fd_funk_txn_t * txn_map = fd_funk_txn_map( funk, wksp );
     279    22026408 :   TEST( txn_map );
     280    22026408 :   TEST( txn_max==fd_funk_txn_map_key_max( txn_map ) );
     281    22026408 :   TEST( seed   ==fd_funk_txn_map_seed   ( txn_map ) );
     282             : 
     283    22026408 :   ulong child_head_idx = fd_funk_txn_idx( funk->child_head_cidx );
     284    22026408 :   ulong child_tail_idx = fd_funk_txn_idx( funk->child_tail_cidx );
     285             : 
     286    22026408 :   int null_child_head = fd_funk_txn_idx_is_null( child_head_idx );
     287    22026408 :   int null_child_tail = fd_funk_txn_idx_is_null( child_tail_idx );
     288             : 
     289    22026408 :   if( !txn_max ) TEST( null_child_head & null_child_tail );
     290    22026402 :   else {
     291    22026402 :     if( null_child_head ) TEST( null_child_tail );
     292    15354951 :     else                  TEST( child_head_idx<txn_max );
     293             : 
     294    22026402 :     if( null_child_tail ) TEST( null_child_head );
     295    15354951 :     else                  TEST( child_tail_idx<txn_max );
     296    22026402 :   }
     297             : 
     298    22026408 :   if( !txn_max ) TEST( fd_funk_txn_idx_is_null( child_tail_idx ) );
     299             : 
     300    22026408 :   fd_funk_txn_xid_t const * root = fd_funk_root( funk );
     301    22026408 :   TEST( root ); /* Practically guaranteed */
     302    22026408 :   TEST( fd_funk_txn_xid_eq_root( root ) );
     303             : 
     304    22026408 :   fd_funk_txn_xid_t * last_publish = funk->last_publish;
     305    22026408 :   TEST( last_publish ); /* Practically guaranteed */
     306             :   /* (*last_publish) only be root at creation and anything but root
     307             :      post creation.  But we don't which situation applies here so this
     308             :      could be anything. */
     309             : 
     310    22026408 :   TEST( !fd_funk_txn_verify( funk ) );
     311             : 
     312             :   /* Test record map */
     313             : 
     314    22026408 :   ulong rec_max = funk->rec_max;
     315    22026408 :   TEST( rec_max<=FD_FUNK_TXN_IDX_NULL );
     316             : 
     317    22026408 :   ulong rec_map_gaddr = funk->rec_map_gaddr;
     318    22026408 :   TEST( rec_map_gaddr );
     319    22026408 :   TEST( fd_wksp_tag( wksp, rec_map_gaddr-1UL )==wksp_tag ); /* When rec_max is zero, rec_map_gaddr can be first byte after alloc */
     320    22026408 :   fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
     321    22026408 :   TEST( rec_map );
     322    22026408 :   TEST( rec_max==fd_funk_rec_map_key_max( rec_map ) );
     323    22026408 :   TEST( seed   ==fd_funk_rec_map_seed   ( rec_map ) );
     324             : 
     325    22026408 :   ulong rec_head_idx = funk->rec_head_idx;
     326    22026408 :   ulong rec_tail_idx = funk->rec_tail_idx;
     327             : 
     328    22026408 :   int null_rec_head = fd_funk_rec_idx_is_null( rec_head_idx );
     329    22026408 :   int null_rec_tail = fd_funk_rec_idx_is_null( rec_tail_idx );
     330             : 
     331    22026408 :   if( !rec_max ) TEST( null_rec_head & null_rec_tail );
     332    22026402 :   else {
     333    22026402 :     if( null_rec_head ) TEST( null_rec_tail );
     334    18863784 :     else                TEST( rec_head_idx<rec_max );
     335             : 
     336    22026402 :     if( null_rec_tail ) TEST( null_rec_head );
     337    18863784 :     else                TEST( rec_tail_idx<rec_max );
     338    22026402 :   }
     339             : 
     340    22026408 :   if( !rec_max ) TEST( fd_funk_rec_idx_is_null( rec_tail_idx ) );
     341             : 
     342    22026408 :   TEST( !fd_funk_rec_verify( funk ) );
     343    22026408 :   TEST( !fd_funk_part_verify( funk ) );
     344             : 
     345             :   /* Test values */
     346             : 
     347    22026408 :   ulong alloc_gaddr = funk->alloc_gaddr;
     348    22026408 :   TEST( alloc_gaddr );
     349    22026408 :   TEST( fd_wksp_tag( wksp, alloc_gaddr )==wksp_tag );
     350    22026408 :   fd_alloc_t * alloc = fd_funk_alloc( funk, wksp );
     351    22026408 :   TEST( alloc );
     352             : 
     353    22026408 :   TEST( !fd_funk_val_verify( funk ) );
     354             : 
     355    22026408 : # undef TEST
     356             : 
     357    22026408 :   return FD_FUNK_SUCCESS;
     358    22026408 : }
     359             : 
     360             : static char *
     361           0 : fd_smart_size( ulong sz, char * tmp, size_t tmpsz ) {
     362           0 :   if( sz <= (1UL<<7) )
     363           0 :     snprintf( tmp, tmpsz, "%lu B", sz );
     364           0 :   else if( sz <= (1UL<<17) )
     365           0 :     snprintf( tmp, tmpsz, "%.3f KB", ((double)sz/((double)(1UL<<10))) );
     366           0 :   else if( sz <= (1UL<<27) )
     367           0 :     snprintf( tmp, tmpsz, "%.3f MB", ((double)sz/((double)(1UL<<20))) );
     368           0 :   else
     369           0 :     snprintf( tmp, tmpsz, "%.3f GB", ((double)sz/((double)(1UL<<30))) );
     370           0 :   return tmp;
     371           0 : }
     372             : 
     373             : void
     374           0 : fd_funk_log_mem_usage( fd_funk_t * funk ) {
     375           0 :   char tmp1[100];
     376           0 :   char tmp2[100];
     377             : 
     378           0 :   FD_LOG_NOTICE(( "funk base footprint: %s",
     379           0 :                   fd_smart_size( fd_funk_footprint(), tmp1, sizeof(tmp1) ) ));
     380           0 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
     381           0 :   fd_funk_txn_t const * txn_map = fd_funk_txn_map( funk, wksp );
     382           0 :   FD_LOG_NOTICE(( "txn table footprint: %s (%lu entries used out of %lu, %lu%%)",
     383           0 :                   fd_smart_size( fd_funk_txn_map_footprint( funk->txn_max ), tmp1, sizeof(tmp1) ),
     384           0 :                   fd_funk_txn_map_key_cnt( txn_map ),
     385           0 :                   fd_funk_txn_map_key_max( txn_map ),
     386           0 :                   (100U*fd_funk_txn_map_key_cnt( txn_map )) / fd_funk_txn_map_key_max( txn_map ) ));
     387           0 :   fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
     388           0 :   FD_LOG_NOTICE(( "rec table footprint: %s (%lu entries used out of %lu, %lu%%)",
     389           0 :                   fd_smart_size( fd_funk_rec_map_footprint( funk->rec_max ), tmp1, sizeof(tmp1) ),
     390           0 :                   fd_funk_rec_map_key_cnt( rec_map ),
     391           0 :                   fd_funk_rec_map_key_max( rec_map ),
     392           0 :                   (100U*fd_funk_rec_map_key_cnt( rec_map )) / fd_funk_rec_map_key_max( rec_map ) ));
     393           0 :   ulong val_cnt = 0;
     394           0 :   ulong val_min = ULONG_MAX;
     395           0 :   ulong val_max = 0;
     396           0 :   ulong val_used = 0;
     397           0 :   ulong val_alloc = 0;
     398           0 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
     399           0 :        !fd_funk_rec_map_iter_done( rec_map, iter );
     400           0 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
     401           0 :     fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
     402           0 :     val_cnt ++;
     403           0 :     val_min = fd_ulong_min( val_min, rec->val_sz );
     404           0 :     val_max = fd_ulong_max( val_max, rec->val_sz );
     405           0 :     val_used += rec->val_sz;
     406           0 :     val_alloc += rec->val_max;
     407           0 :   }
     408           0 :   FD_LOG_NOTICE(( "  rec count: %lu, min size: %lu, avg_size: %lu, max_size: %lu, total_size: %s, total_allocated: %s",
     409           0 :                   val_cnt, val_min, val_used/val_cnt, val_max,
     410           0 :                   fd_smart_size( val_used, tmp1, sizeof(tmp1) ),
     411           0 :                   fd_smart_size( val_alloc, tmp2, sizeof(tmp2) ) ));
     412           0 :   FD_LOG_NOTICE(( "part vec footprint: %s",
     413           0 :                   fd_smart_size( fd_funk_partvec_footprint(0U), tmp1, sizeof(tmp1) ) ));
     414           0 : }
     415             : 
     416             : #include "../flamenco/fd_rwlock.h"
     417             : static fd_rwlock_t lock[ 1 ] = {0};
     418             : 
     419             : void
     420     1570863 : fd_funk_start_write( fd_funk_t * funk ) {
     421     1570863 :   fd_rwlock_write( lock );
     422             : #ifdef FD_FUNK_WKSP_PROTECT
     423             :   fd_wksp_mprotect( fd_funk_wksp( funk ), 0 );
     424             : #endif
     425     1570863 : # if FD_HAS_THREADS
     426     1570863 :   register ulong oldval;
     427     1570863 :   for(;;) {
     428     1570863 :     oldval = funk->write_lock;
     429     1570863 :     if( FD_LIKELY( FD_ATOMIC_CAS( &funk->write_lock, oldval, oldval+1U) == oldval ) ) break;
     430           0 :     FD_SPIN_PAUSE();
     431           0 :   }
     432     1570863 :   if( FD_UNLIKELY(oldval&1UL) ) {
     433           0 :      FD_LOG_CRIT(( "attempt to lock funky when it is already locked" ));
     434           0 :   }
     435     1570863 :   FD_COMPILER_MFENCE();
     436             : # else
     437             :   (void)funk;
     438             : # endif
     439     1570863 : }
     440             : 
     441             : void
     442     1570863 : fd_funk_end_write( fd_funk_t * funk ) {
     443     1570863 : # if FD_HAS_THREADS
     444     1570863 :   FD_COMPILER_MFENCE();
     445     1570863 :   register ulong oldval;
     446     1570863 :   for(;;) {
     447     1570863 :     oldval = funk->write_lock;
     448     1570863 :     if( FD_LIKELY( FD_ATOMIC_CAS( &funk->write_lock, oldval, oldval+1U) == oldval ) ) break;
     449           0 :     FD_SPIN_PAUSE();
     450           0 :   }
     451     1570863 :   if( FD_UNLIKELY(!(oldval&1UL)) ) {
     452           0 :     FD_LOG_CRIT(( "attempt to unlock funky when it is already unlocked" ));
     453           0 :   }
     454             : # else
     455             :   (void)funk;
     456             : # endif
     457             : #ifdef FD_FUNK_WKSP_PROTECT
     458             :   fd_wksp_mprotect( fd_funk_wksp( funk ), 1 );
     459             : #endif
     460     1570863 :   fd_rwlock_unwrite( lock );
     461     1570863 : }
     462             : 
     463             : void
     464   734828787 : fd_funk_check_write( fd_funk_t * funk ) {
     465   734828787 :   ulong val = funk->write_lock;
     466   734828787 :   if( FD_UNLIKELY(!(val&1UL)) ) FD_LOG_CRIT(( "missing call to fd_funk_start_write" ));
     467   734828787 : }
     468             : 
     469             : void
     470           0 : fd_funk_speed_load_mode( fd_funk_t * funk, int flag ) {
     471           0 :   funk->speed_load = flag;
     472           0 : }

Generated by: LCOV version 1.14