LCOV - code coverage report
Current view: top level - util/wksp - fd_wksp_helper.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 22 314 7.0 %
Date: 2026-03-19 18:19:27 Functions: 3 26 11.5 %

          Line data    Source code
       1             : #include "fd_wksp_private.h"
       2             : #include "../pod/fd_pod.h"
       3             : 
       4             : /* fd_wksp_private_{join,leave}_func are used to automagically handle
       5             :    the first join / last leave by the fd_wksp_attach / fd_wksp_detach. */
       6             : 
       7             : static void *
       8             : fd_wksp_private_join_func( void *                       context,
       9           0 :                            fd_shmem_join_info_t const * info ) {
      10           0 :   (void)context;
      11           0 :   return fd_wksp_join( info->shmem ); /* logs details */
      12           0 : }
      13             : 
      14             : static void *
      15             : fd_wksp_private_leave_func( void *                       context,
      16           0 :                             fd_shmem_join_info_t const * info ) {
      17           0 :   (void)context;
      18           0 :   return fd_wksp_leave( info->join ); /* logs details */
      19           0 : }
      20             : 
      21             : /* fd_wksp_private_cstr populates cstr with [name]:[gaddr].  Assumes
      22             :    name is a valid wksp shmem name and that cstr is at least
      23             :    FD_WKSP_CSTR_MAX bytes.  Returns cstr. */
      24             : 
      25             : static char *
      26             : fd_wksp_private_cstr( char const * name,
      27             :                       ulong        gaddr,
      28           0 :                       char *       cstr ) {
      29           0 :   fd_cstr_fini( fd_cstr_append_ulong_as_text( fd_cstr_append_char( fd_cstr_append_cstr( fd_cstr_init( cstr ),
      30           0 :     name ), ':' ), ' ', '\0', gaddr, fd_ulong_base10_dig_cnt( gaddr ) ) );
      31           0 :   return cstr;
      32           0 : }
      33             : 
      34             : /* fd_wksp_private_cstr_parse extracts the name and gaddr from a
      35             :    [name]:[gaddr] cstr.  This doesn't actually validate if name is a
      36             :    compliant fd_shmem_name.  That will be handled automatically by the
      37             :    fd_shmem APIs. */
      38             : 
      39             : static char *                                      /* Returns name on success, NULL on failure (logs details) */
      40             : fd_wksp_private_cstr_parse( char const * cstr,     /* cstr to parse */
      41             :                             char *       name,     /* Non-NULL, room for FD_SHMEM_NAME_MAX bytes, holds name on success,
      42             :                                                       potentially clobbered otherwise */
      43           0 :                             ulong *      gaddr ) { /* Non-NULL, holds gaddr on success, untouched otherwise */
      44           0 :   if( FD_UNLIKELY( !cstr ) ) {
      45           0 :     FD_LOG_WARNING(( "NULL cstr" ));
      46           0 :     return NULL;
      47           0 :   }
      48             : 
      49           0 :   ulong len      = 0UL;
      50           0 :   ulong name_len = ULONG_MAX;
      51           0 :   for(;;) {
      52           0 :     if( cstr[len]=='\0' ) break;
      53           0 :     if( cstr[len]==':' ) name_len = len;
      54           0 :     len++;
      55           0 :   }
      56           0 :   ulong gaddr_len = len - name_len - 1UL;
      57             : 
      58           0 :   if( FD_UNLIKELY( !name_len ) ) {
      59           0 :     FD_LOG_WARNING(( "no name found; cstr should be of the form [name]:[gaddr]" ));
      60           0 :     return NULL;
      61           0 :   }
      62             : 
      63           0 :   if( FD_UNLIKELY( name_len==ULONG_MAX ) ) {
      64           0 :     FD_LOG_WARNING((  "no ':' found; cstr should be of the form [name]:[gaddr]" ));
      65           0 :     return NULL;
      66           0 :   }
      67             : 
      68           0 :   if( FD_UNLIKELY( !gaddr_len ) ) {
      69           0 :     FD_LOG_WARNING(( "no gaddr found; cstr should be of the form [name]:[gaddr]" ));
      70           0 :     return NULL;
      71           0 :   }
      72             : 
      73           0 :   if( FD_UNLIKELY( name_len>=FD_SHMEM_NAME_MAX ) ) {
      74           0 :     FD_LOG_WARNING(( "name too long" ));
      75           0 :     return NULL;
      76           0 :   }
      77             : 
      78           0 :   fd_memcpy( name, cstr, name_len );
      79           0 :   name[name_len] = '\0';
      80           0 :   gaddr[0] = fd_cstr_to_ulong( cstr + name_len + 1UL );
      81           0 :   return name;
      82           0 : }
      83             : 
      84             : /* shmem helper APIs **************************************************/
      85             : 
      86             : /* fd_ulong_sum_sat computes sum x[i] for i in [0,cnt), saturating at
      87             :    ULONG_MAX if the sum would overflow.  TODO: MOVE TO SAT LIBRARY */
      88             : 
      89             : FD_FN_PURE static inline ulong
      90             : fd_ulong_sum_sat( ulong         cnt,
      91           0 :                   ulong const * x ) {
      92           0 :   ulong sum  = 0UL;
      93           0 :   int   ovfl = 0;
      94           0 :   for( ulong idx=0UL; idx<cnt; idx++ ) {
      95           0 :     ulong tmp = sum + x[idx];
      96           0 :     ovfl |= (tmp < sum );
      97           0 :     sum = tmp;
      98           0 :   }
      99           0 :   return fd_ulong_if( ovfl, ULONG_MAX, sum );
     100           0 : }
     101             : 
     102             : int
     103             : fd_wksp_new_named( char const *  name,
     104             :                    ulong         page_sz,
     105             :                    ulong         sub_cnt,
     106             :                    ulong const * sub_page_cnt,
     107             :                    ulong const * sub_cpu_idx,
     108             :                    ulong         mode,
     109             :                    uint          seed,
     110           0 :                    ulong         part_max ) {
     111             : 
     112             :   /* Check input args */
     113             : 
     114           0 :   if( FD_UNLIKELY( !fd_shmem_name_len( name )      ) ) { FD_LOG_WARNING(( "bad name"            )); return FD_WKSP_ERR_INVAL; }
     115           0 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return FD_WKSP_ERR_INVAL; }
     116           0 :   if( FD_UNLIKELY( !sub_cnt                        ) ) { FD_LOG_WARNING(( "zero sub_cnt"        )); return FD_WKSP_ERR_INVAL; }
     117           0 :   if( FD_UNLIKELY( !sub_page_cnt                   ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt"   )); return FD_WKSP_ERR_INVAL; }
     118           0 :   if( FD_UNLIKELY( !sub_cpu_idx                    ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx"    )); return FD_WKSP_ERR_INVAL; }
     119             : 
     120           0 :   ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
     121             : 
     122           0 :   if( FD_UNLIKELY( !page_cnt                       ) ) { FD_LOG_WARNING(( "zero page_cnt"       )); return FD_WKSP_ERR_INVAL; }
     123           0 :   if( FD_UNLIKELY( page_cnt>=(ULONG_MAX/page_sz)   ) ) { FD_LOG_WARNING(( "page_cnt overflow"   )); return FD_WKSP_ERR_INVAL; }
     124             : 
     125             :   /* Configure the wksp */
     126             : 
     127           0 :   ulong footprint = page_cnt*page_sz;
     128             : 
     129           0 :   if( !part_max ) {
     130           0 :     part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
     131           0 :     if( FD_UNLIKELY( !part_max ) ) { /* should not happen for typical page_sz and non-zero page_cnt */
     132           0 :       FD_LOG_WARNING(( "fd_wksp_part_max_est(%lu,64KiB) failed", footprint ));
     133           0 :       return FD_WKSP_ERR_INVAL;
     134           0 :     }
     135           0 :   }
     136             : 
     137           0 :   ulong data_max = fd_wksp_data_max_est( footprint, part_max );
     138           0 :   if( FD_UNLIKELY( !data_max ) ) {
     139           0 :     FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
     140           0 :     return FD_WKSP_ERR_INVAL;
     141           0 :   }
     142             : 
     143             :   /* Create the memory region */
     144             : 
     145           0 :   int err = fd_shmem_create_multi( name, page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx, mode ); /* logs details */
     146           0 :   if( FD_UNLIKELY( err ) ) return FD_WKSP_ERR_FAIL;
     147             : 
     148             :   /* Join the memory region */
     149             : 
     150           0 :   void * shmem = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, 0, NULL, NULL, NULL ); /* logs details */
     151           0 :   if( FD_UNLIKELY( !shmem ) ) {
     152           0 :     fd_shmem_unlink( name, page_sz ); /* logs details */
     153           0 :     return FD_WKSP_ERR_FAIL;
     154           0 :   }
     155             : 
     156             :   /* Format the region as a workspace */
     157             : 
     158           0 :   if( FD_UNLIKELY( !fd_wksp_new( shmem, name, seed, part_max, data_max ) ) ) { /* logs details */
     159           0 :     fd_shmem_unlink( name, page_sz ); /* logs details */
     160           0 :     fd_shmem_leave( shmem, NULL, NULL ); /* logs details, after the unlink as per unix file semantics */
     161           0 :     return FD_WKSP_ERR_FAIL;
     162           0 :   }
     163             : 
     164           0 :   fd_shmem_leave( shmem, NULL, NULL ); /* logs details */
     165             : 
     166           0 :   return FD_WKSP_SUCCESS;
     167           0 : }
     168             : 
     169             : int
     170           0 : fd_wksp_delete_named( char const * name ) {
     171             : 
     172             :   /* Join the region and get the page size */
     173             : 
     174           0 :   fd_shmem_join_info_t info[1];
     175           0 :   void * shwksp = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, 0, NULL, NULL, info ); /* logs details */
     176           0 :   if( FD_UNLIKELY( !shwksp ) ) return FD_WKSP_ERR_FAIL;
     177           0 :   ulong page_sz = info->page_sz;
     178             : 
     179             :   /* Delete the region */
     180             : 
     181           0 :   if( FD_UNLIKELY( !fd_wksp_delete( shwksp ) ) ) { /* logs details */
     182           0 :     fd_shmem_leave( shwksp, NULL, NULL );
     183           0 :     return FD_WKSP_ERR_FAIL;
     184           0 :   }
     185             : 
     186           0 :   if( FD_UNLIKELY( fd_shmem_unlink( name, page_sz ) ) ) { /* logs details */
     187           0 :     fd_shmem_leave( shwksp, NULL, NULL );
     188           0 :     return FD_WKSP_ERR_FAIL;
     189           0 :   }
     190             : 
     191           0 :   fd_shmem_leave( shwksp, NULL, NULL ); /* logs details, after the unlink as per UNIX file semantics */
     192           0 :   return FD_WKSP_SUCCESS;
     193           0 : }
     194             : 
     195             : fd_wksp_t *
     196             : fd_wksp_new_anon( char const *  name,
     197             :                   ulong         page_sz,
     198             :                   ulong         sub_cnt,
     199             :                   ulong const * sub_page_cnt,
     200             :                   ulong const * sub_cpu_idx,
     201             :                   uint          seed,
     202           0 :                   ulong         part_max ) {
     203             : 
     204             :   /* Check input args */
     205             : 
     206           0 :   if( FD_UNLIKELY( !fd_shmem_name_len( name )      ) ) { FD_LOG_WARNING(( "bad name"            )); return NULL; }
     207           0 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return NULL; }
     208           0 :   if( FD_UNLIKELY( !sub_cnt                        ) ) { FD_LOG_WARNING(( "zero sub_cnt"        )); return NULL; }
     209           0 :   if( FD_UNLIKELY( !sub_page_cnt                   ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt"   )); return NULL; }
     210           0 :   if( FD_UNLIKELY( !sub_cpu_idx                    ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx"    )); return NULL; }
     211             : 
     212           0 :   ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
     213             : 
     214           0 :   if( FD_UNLIKELY( !page_cnt                       ) ) { FD_LOG_WARNING(( "zero page_cnt"       )); return NULL; }
     215           0 :   if( FD_UNLIKELY( page_cnt>=(ULONG_MAX/page_sz)   ) ) { FD_LOG_WARNING(( "page_cnt overflow"   )); return NULL; }
     216             : 
     217             :   /* Configure the wksp */
     218             : 
     219           0 :   ulong footprint = page_cnt*page_sz;
     220             : 
     221           0 :   if( !part_max ) {
     222           0 :     part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
     223           0 :     if( FD_UNLIKELY( !part_max ) ) { /* should not happen for typical page_sz and non-zero page_cnt */
     224           0 :       FD_LOG_WARNING(( "fd_wksp_part_max_est(%lu,64KiB) failed", footprint ));
     225           0 :       return NULL;
     226           0 :     }
     227           0 :   }
     228             : 
     229           0 :   ulong data_max = fd_wksp_data_max_est( footprint, part_max );
     230           0 :   if( FD_UNLIKELY( !data_max ) ) {
     231           0 :     FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
     232           0 :     return NULL;
     233           0 :   }
     234             : 
     235             :   /* Acquire the pages */
     236             : 
     237           0 :   void * shmem = fd_shmem_acquire_multi( page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx ); /* logs details */
     238           0 :   if( FD_UNLIKELY( !shmem ) ) return NULL;
     239             : 
     240             :   /* Format the memory as wksp */
     241             : 
     242           0 :   void* shwksp = fd_wksp_new( shmem, name, seed, part_max, data_max ); /* logs details */
     243           0 :   if( FD_UNLIKELY( !shwksp ) ) {
     244           0 :     fd_shmem_release( shmem, page_sz, page_cnt ); /* logs details */
     245           0 :     return NULL;
     246           0 :   }
     247             : 
     248             :   /* Join the wksp */
     249             : 
     250           0 :   fd_wksp_t * wksp = fd_wksp_join( shwksp ); /* logs details */
     251           0 :   if( FD_UNLIKELY( !wksp ) ) {
     252           0 :     fd_shmem_release( fd_wksp_delete( shwksp ), page_sz, page_cnt ); /* logs details */
     253           0 :     return NULL;
     254           0 :   }
     255             : 
     256             :   /* Register the join */
     257             : 
     258           0 :   if( FD_UNLIKELY( fd_shmem_join_anonymous( name, FD_SHMEM_JOIN_MODE_READ_WRITE, wksp, shmem, page_sz, page_cnt ) ) ) { /* logs */
     259           0 :     fd_shmem_release( fd_wksp_delete( fd_wksp_leave( wksp ) ), page_sz, page_cnt ); /* logs details */
     260           0 :     return NULL;
     261           0 :   }
     262             : 
     263           0 :   return wksp;
     264           0 : }
     265             : 
     266             : void
     267           0 : fd_wksp_delete_anon( fd_wksp_t * wksp ) {
     268           0 :   fd_shmem_join_info_t info[1];
     269           0 :   if( FD_UNLIKELY( fd_shmem_leave_anonymous( wksp, info ) ) ) return; /* logs details */
     270           0 :   fd_shmem_release( fd_wksp_delete( fd_wksp_leave( wksp ) ), info->page_sz, info->page_cnt ); /* logs details */
     271           0 : }
     272             : 
     273             : fd_wksp_t *
     274           0 : fd_wksp_attach( char const * name ) {
     275           0 :   return (fd_wksp_t *)
     276           0 :     fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, 0, fd_wksp_private_join_func, NULL, NULL ); /* logs details */
     277           0 : }
     278             : 
     279             : int
     280           0 : fd_wksp_detach( fd_wksp_t * wksp ) {
     281           0 :   if( FD_UNLIKELY( !wksp ) ) {
     282           0 :     FD_LOG_WARNING(( "NULL wksp" ));
     283           0 :     return 1;
     284           0 :   }
     285           0 :   return fd_shmem_leave( wksp, fd_wksp_private_leave_func, NULL ); /* logs details */
     286           0 : }
     287             : 
     288             : fd_wksp_t *
     289         221 : fd_wksp_containing( void const * laddr ) {
     290         221 :   if( FD_UNLIKELY( !laddr ) ) return NULL;
     291             : 
     292         221 :   fd_shmem_join_info_t info[1];
     293         221 :   if( FD_UNLIKELY( fd_shmem_join_query_by_addr( laddr, 1UL, info ) ) ) return NULL;
     294             : 
     295         221 :   fd_wksp_t * wksp = (fd_wksp_t *)info->join;
     296         221 :   if( FD_UNLIKELY( !wksp ) ) return NULL;
     297             : 
     298         221 :   if( FD_UNLIKELY( wksp->magic!=FD_WKSP_MAGIC ) ) return NULL;
     299             : 
     300         221 :   return wksp;
     301         221 : }
     302             : 
     303             : void *
     304             : fd_wksp_alloc_laddr( fd_wksp_t * wksp,
     305             :                      ulong       align,
     306             :                      ulong       sz,
     307         137 :                      ulong       tag ) {
     308         137 :   ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
     309         137 :   if( FD_UNLIKELY( !gaddr ) ) return NULL;
     310         137 :   return fd_wksp_laddr_fast( wksp, gaddr );
     311         137 : }
     312             : 
     313             : void
     314         113 : fd_wksp_free_laddr( void * laddr ) {
     315         113 :   if( FD_UNLIKELY( !laddr ) ) return;
     316             : 
     317         113 :   fd_wksp_t * wksp = fd_wksp_containing( laddr );
     318         113 :   if( FD_UNLIKELY( !wksp ) ) {
     319           0 :     FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
     320           0 :     return;
     321           0 :   }
     322             : 
     323         113 :   ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
     324         113 :   if( FD_UNLIKELY( !((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) {
     325           0 :     FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
     326           0 :     return;
     327           0 :   }
     328             : 
     329         113 :   fd_wksp_free( wksp, gaddr );
     330         113 : }
     331             : 
     332             : /* cstr helper APIs ***************************************************/
     333             : 
     334             : char *
     335             : fd_wksp_cstr( fd_wksp_t const * wksp,
     336             :               ulong             gaddr,
     337           0 :               char *            cstr ) {
     338           0 :   if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
     339           0 :   if( FD_UNLIKELY( !wksp ) ) { FD_LOG_WARNING(( "NULL wksp" )); return NULL; }
     340             : 
     341           0 :   if( FD_UNLIKELY( !( (!gaddr) | ((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) ) {
     342           0 :     FD_LOG_WARNING(( "unmappable gaddr" ));
     343           0 :     return NULL;
     344           0 :   }
     345             : 
     346           0 :   return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
     347           0 : }
     348             : 
     349             : char *
     350             : fd_wksp_cstr_laddr( void const * laddr,
     351           0 :                     char *       cstr ) {
     352           0 :   if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
     353             : 
     354           0 :   fd_wksp_t const * wksp = fd_wksp_containing( laddr );
     355           0 :   if( FD_UNLIKELY( !wksp ) ) {
     356           0 :     FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
     357           0 :     return NULL;
     358           0 :   }
     359             : 
     360           0 :   ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
     361           0 :   if( FD_UNLIKELY( !((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) {
     362           0 :     FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
     363           0 :     return 0UL;
     364           0 :   }
     365             : 
     366           0 :   return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
     367           0 : }
     368             : 
     369             : char *
     370             : fd_wksp_cstr_alloc( char const * name,
     371             :                     ulong        align,
     372             :                     ulong        sz,
     373             :                     ulong        tag,
     374           0 :                     char *       cstr ) {
     375           0 :   if( FD_UNLIKELY( !cstr ) ) {
     376           0 :     FD_LOG_WARNING(( "NULL cstr" ));
     377           0 :     return NULL;
     378           0 :   }
     379             : 
     380           0 :   fd_wksp_t * wksp = fd_wksp_attach( name );
     381           0 :   if( FD_UNLIKELY( !wksp ) ) return NULL; /* logs details */
     382             :   /* name must be valid at this point */
     383             : 
     384           0 :   ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
     385           0 :   if( FD_UNLIKELY( (!!sz) & (!gaddr) ) ) {
     386           0 :     fd_wksp_detach( wksp ); /* logs details */
     387           0 :     return NULL;
     388           0 :   }
     389             : 
     390           0 :   fd_wksp_detach( wksp ); /* logs details */
     391           0 :   return fd_wksp_private_cstr( name, gaddr, cstr );
     392           0 : }
     393             : 
     394             : void
     395           0 : fd_wksp_cstr_free( char const * cstr ) {
     396           0 :   char  name[ FD_SHMEM_NAME_MAX ];
     397           0 :   ulong gaddr;
     398           0 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
     399             : 
     400           0 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     401           0 :   if( FD_UNLIKELY( !wksp ) ) return;
     402             : 
     403           0 :   fd_wksp_free( wksp, gaddr ); /* logs details */
     404             : 
     405           0 :   fd_wksp_detach( wksp ); /* logs details */
     406           0 : }
     407             : 
     408             : ulong
     409           0 : fd_wksp_cstr_tag( char const * cstr ) {
     410           0 :   char  name[ FD_SHMEM_NAME_MAX ];
     411           0 :   ulong gaddr;
     412           0 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return 0UL; /* logs details */
     413             : 
     414           0 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     415           0 :   if( FD_UNLIKELY( !wksp ) ) return 0UL;
     416             : 
     417           0 :   ulong tag = fd_wksp_tag( wksp, gaddr ); /* logs details */
     418             : 
     419           0 :   fd_wksp_detach( wksp ); /* logs details */
     420             : 
     421           0 :   return tag;
     422           0 : }
     423             : 
     424             : void
     425             : fd_wksp_cstr_memset( char const * cstr,
     426           0 :                      int          c ) {
     427           0 :   char  name[ FD_SHMEM_NAME_MAX ];
     428           0 :   ulong gaddr;
     429           0 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
     430             : 
     431           0 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     432           0 :   if( FD_UNLIKELY( !wksp ) ) return;
     433             : 
     434           0 :   fd_wksp_memset( wksp, gaddr, c ); /* logs details */
     435             : 
     436           0 :   fd_wksp_detach( wksp ); /* logs details */
     437           0 : }
     438             : 
     439             : void *
     440           0 : fd_wksp_map( char const * cstr ) {
     441           0 :   char  name[ FD_SHMEM_NAME_MAX ];
     442           0 :   ulong gaddr;
     443           0 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return NULL; /* logs details */
     444             : 
     445           0 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     446           0 :   if( FD_UNLIKELY( !wksp ) ) return NULL;
     447             : 
     448           0 :   void * laddr = fd_wksp_laddr( wksp, gaddr ); /* logs details */
     449           0 :   if( FD_UNLIKELY( !laddr ) ) {
     450             :     /* We do a detach here regardless of this being an error case or not
     451             :        (i.e. gaddr was NULL) because unmap will not be able to figure
     452             :        out which wksp corresponds to the returned NULL */
     453           0 :     fd_wksp_detach( wksp ); /* logs details */
     454           0 :     return NULL;
     455           0 :   }
     456             : 
     457           0 :   return laddr;
     458           0 : }
     459             : 
     460             : void
     461           0 : fd_wksp_unmap( void const * laddr ) {
     462           0 :   if( FD_UNLIKELY( !laddr ) ) return; /* Silent because NULL might not be an error case (i.e. gaddr passed to map was 0/NULL) */
     463             : 
     464             :   /* Technically more efficient given current implementation to do:
     465             :        shmem_leave_addr( laddr );
     466             :      but the below is more official from a software maintainability POV */
     467             : 
     468           0 :   fd_shmem_join_info_t info[1];
     469           0 :   if( FD_UNLIKELY( fd_shmem_join_query_by_addr( laddr, 1UL, info ) ) ) {
     470           0 :     FD_LOG_WARNING(( "laddr does not seem to be from fd_wksp_map" ));
     471           0 :     return;
     472           0 :   }
     473             : 
     474           0 :   fd_wksp_t * wksp = (fd_wksp_t *)info->join;
     475           0 :   if( FD_UNLIKELY( !wksp ) ) {
     476           0 :     FD_LOG_WARNING(( "Called within fd_wksp_join or fd_wksp_leave??" ));
     477           0 :     return;
     478           0 :   }
     479             : 
     480           0 :   fd_wksp_detach( wksp ); /* logs details */
     481           0 : }
     482             : 
     483             : /* pod helper APIs ****************************************************/
     484             : 
     485             : uchar const *
     486           0 : fd_wksp_pod_attach( char const * gaddr ) {
     487           0 :   if( FD_UNLIKELY( !gaddr ) ) FD_LOG_ERR(( "NULL gaddr" ));
     488             : 
     489           0 :   void * obj = fd_wksp_map( gaddr );
     490           0 :   if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "Unable to map pod at gaddr %s into local address space", gaddr ));
     491             : 
     492           0 :   uchar const * pod = fd_pod_join( obj );
     493           0 :   if( FD_UNLIKELY( !pod ) ) FD_LOG_ERR(( "fd_pod_join to pod at gaddr %s failed", gaddr ));
     494             : 
     495           0 :   return pod;
     496           0 : }
     497             : 
     498             : void
     499           0 : fd_wksp_pod_detach( uchar const * pod ) {
     500           0 :   if( FD_UNLIKELY( !pod ) ) FD_LOG_ERR(( "NULL pod" ));
     501             : 
     502           0 :   void * obj = fd_pod_leave( pod );
     503           0 :   if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "fd_pod_leave failed" ));
     504             : 
     505           0 :   fd_wksp_unmap( obj ); /* logs details */
     506           0 : }
     507             : 
     508             : void *
     509             : fd_wksp_pod_map( uchar const * pod,
     510           0 :                  char const *  path ) {
     511           0 :   if( FD_UNLIKELY( !pod  ) ) FD_LOG_ERR(( "NULL pod"  ));
     512           0 :   if( FD_UNLIKELY( !path ) ) FD_LOG_ERR(( "NULL path" ));
     513             : 
     514           0 :   char const * gaddr = fd_pod_query_cstr( pod, path, NULL );
     515           0 :   if( FD_UNLIKELY( !gaddr ) ) FD_LOG_ERR(( "cstr path %s not found in pod", path ));
     516             : 
     517           0 :   void * obj = fd_wksp_map( gaddr );
     518           0 :   if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "Unable to map pod cstr path %s (%s) into local address space", path, gaddr ));
     519             : 
     520           0 :   return obj;
     521           0 : }
     522             : 
     523             : void
     524           0 : fd_wksp_pod_unmap( void * obj ) {
     525           0 :   if( FD_UNLIKELY( !obj ) ) FD_LOG_ERR(( "NULL obj" ));
     526             : 
     527           0 :   fd_wksp_unmap( obj ); /* logs details */
     528           0 : }

Generated by: LCOV version 1.14