LCOV - code coverage report
Current view: top level - util/wksp - fd_wksp_helper.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 235 314 74.8 %
Date: 2025-07-01 05:00:49 Functions: 22 26 84.6 %

          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        1836 :                            fd_shmem_join_info_t const * info ) {
      10        1836 :   (void)context;
      11        1836 :   return fd_wksp_join( info->shmem ); /* logs details */
      12        1836 : }
      13             : 
      14             : static void *
      15             : fd_wksp_private_leave_func( void *                       context,
      16        1746 :                             fd_shmem_join_info_t const * info ) {
      17        1746 :   (void)context;
      18        1746 :   return fd_wksp_leave( info->join ); /* logs details */
      19        1746 : }
      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         258 :                       char *       cstr ) {
      29         258 :   fd_cstr_fini( fd_cstr_append_ulong_as_text( fd_cstr_append_char( fd_cstr_append_cstr( fd_cstr_init( cstr ),
      30         258 :     name ), ':' ), ' ', '\0', gaddr, fd_ulong_base10_dig_cnt( gaddr ) ) );
      31         258 :   return cstr;
      32         258 : }
      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        1353 :                             ulong *      gaddr ) { /* Non-NULL, holds gaddr on success, untouched otherwise */
      44        1353 :   if( FD_UNLIKELY( !cstr ) ) {
      45          30 :     FD_LOG_WARNING(( "NULL cstr" ));
      46          30 :     return NULL;
      47          30 :   }
      48             : 
      49        1323 :   ulong len      = 0UL;
      50        1323 :   ulong name_len = ULONG_MAX;
      51       29046 :   for(;;) {
      52       29046 :     if( cstr[len]=='\0' ) break;
      53       27723 :     if( cstr[len]==':' ) name_len = len;
      54       27723 :     len++;
      55       27723 :   }
      56        1323 :   ulong gaddr_len = len - name_len - 1UL;
      57             : 
      58        1323 :   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        1323 :   if( FD_UNLIKELY( name_len==ULONG_MAX ) ) {
      64         141 :     FD_LOG_WARNING((  "no ':' found; cstr should be of the form [name]:[gaddr]" ));
      65         141 :     return NULL;
      66         141 :   }
      67             : 
      68        1182 :   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        1182 :   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        1182 :   fd_memcpy( name, cstr, name_len );
      79        1182 :   name[name_len] = '\0';
      80        1182 :   gaddr[0] = fd_cstr_to_ulong( cstr + name_len + 1UL );
      81        1182 :   return name;
      82        1182 : }
      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         147 :                   ulong const * x ) {
      92         147 :   ulong sum  = 0UL;
      93         147 :   int   ovfl = 0;
      94         294 :   for( ulong idx=0UL; idx<cnt; idx++ ) {
      95         147 :     ulong tmp = sum + x[idx];
      96         147 :     ovfl |= (tmp < sum );
      97         147 :     sum = tmp;
      98         147 :   }
      99         147 :   return fd_ulong_if( ovfl, ULONG_MAX, sum );
     100         147 : }
     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          78 :                    ulong         part_max ) {
     111             : 
     112             :   /* Check input args */
     113             : 
     114          78 :   if( FD_UNLIKELY( !fd_shmem_name_len( name )      ) ) { FD_LOG_WARNING(( "bad name"            )); return FD_WKSP_ERR_INVAL; }
     115          72 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return FD_WKSP_ERR_INVAL; }
     116          66 :   if( FD_UNLIKELY( !sub_cnt                        ) ) { FD_LOG_WARNING(( "zero sub_cnt"        )); return FD_WKSP_ERR_INVAL; }
     117          63 :   if( FD_UNLIKELY( !sub_page_cnt                   ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt"   )); return FD_WKSP_ERR_INVAL; }
     118          60 :   if( FD_UNLIKELY( !sub_cpu_idx                    ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx"    )); return FD_WKSP_ERR_INVAL; }
     119             : 
     120          57 :   ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
     121             : 
     122          57 :   if( FD_UNLIKELY( !page_cnt                       ) ) { FD_LOG_WARNING(( "zero page_cnt"       )); return FD_WKSP_ERR_INVAL; }
     123          51 :   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          48 :   ulong footprint = page_cnt*page_sz;
     128             : 
     129          48 :   if( !part_max ) {
     130          45 :     part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
     131          45 :     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          45 :   }
     136             : 
     137          48 :   ulong data_max = fd_wksp_data_max_est( footprint, part_max );
     138          48 :   if( FD_UNLIKELY( !data_max ) ) {
     139           3 :     FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
     140           3 :     return FD_WKSP_ERR_INVAL;
     141           3 :   }
     142             : 
     143             :   /* Create the memory region */
     144             : 
     145          45 :   int err = fd_shmem_create_multi( name, page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx, mode ); /* logs details */
     146          45 :   if( FD_UNLIKELY( err ) ) return FD_WKSP_ERR_FAIL;
     147             : 
     148             :   /* Join the memory region */
     149             : 
     150          30 :   void * shmem = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, NULL ); /* logs details */
     151          30 :   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          30 :   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          30 :   fd_shmem_leave( shmem, NULL, NULL ); /* logs details */
     165             : 
     166          30 :   return FD_WKSP_SUCCESS;
     167          30 : }
     168             : 
     169             : int
     170          54 : fd_wksp_delete_named( char const * name ) {
     171             : 
     172             :   /* Join the region and get the page size */
     173             : 
     174          54 :   fd_shmem_join_info_t info[1];
     175          54 :   void * shwksp = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, info ); /* logs details */
     176          54 :   if( FD_UNLIKELY( !shwksp ) ) return FD_WKSP_ERR_FAIL;
     177          30 :   ulong page_sz = info->page_sz;
     178             : 
     179             :   /* Delete the region */
     180             : 
     181          30 :   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          30 :   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          30 :   fd_shmem_leave( shwksp, NULL, NULL ); /* logs details, after the unlink as per UNIX file semantics */
     192          30 :   return FD_WKSP_SUCCESS;
     193          30 : }
     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         105 :                   ulong         part_max ) {
     203             : 
     204             :   /* Check input args */
     205             : 
     206         105 :   if( FD_UNLIKELY( !fd_shmem_name_len( name )      ) ) { FD_LOG_WARNING(( "bad name"            )); return NULL; }
     207         102 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "unsupported page_sz" )); return NULL; }
     208          99 :   if( FD_UNLIKELY( !sub_cnt                        ) ) { FD_LOG_WARNING(( "zero sub_cnt"        )); return NULL; }
     209          96 :   if( FD_UNLIKELY( !sub_page_cnt                   ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt"   )); return NULL; }
     210          93 :   if( FD_UNLIKELY( !sub_cpu_idx                    ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx"    )); return NULL; }
     211             : 
     212          90 :   ulong page_cnt = fd_ulong_sum_sat( sub_cnt, sub_page_cnt );
     213             : 
     214          90 :   if( FD_UNLIKELY( !page_cnt                       ) ) { FD_LOG_WARNING(( "zero page_cnt"       )); return NULL; }
     215          87 :   if( FD_UNLIKELY( page_cnt>=(ULONG_MAX/page_sz)   ) ) { FD_LOG_WARNING(( "page_cnt overflow"   )); return NULL; }
     216             : 
     217             :   /* Configure the wksp */
     218             : 
     219          84 :   ulong footprint = page_cnt*page_sz;
     220             : 
     221          84 :   if( !part_max ) {
     222          81 :     part_max = fd_wksp_part_max_est( footprint, 64UL<<10 ); /* Typical size is fd_alloc top level superblock-ish */
     223          81 :     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          81 :   }
     228             : 
     229          84 :   ulong data_max = fd_wksp_data_max_est( footprint, part_max );
     230          84 :   if( FD_UNLIKELY( !data_max ) ) {
     231           3 :     FD_LOG_WARNING(( "part_max (%lu) too large for footprint (%lu)", part_max, footprint ));
     232           3 :     return NULL;
     233           3 :   }
     234             : 
     235             :   /* Acquire the pages */
     236             : 
     237          81 :   void * shmem = fd_shmem_acquire_multi( page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx ); /* logs details */
     238          81 :   if( FD_UNLIKELY( !shmem ) ) return NULL;
     239             : 
     240             :   /* Format the memory as wksp */
     241             : 
     242          78 :   void* shwksp = fd_wksp_new( shmem, name, seed, part_max, data_max ); /* logs details */
     243          78 :   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          78 :   fd_wksp_t * wksp = fd_wksp_join( shwksp ); /* logs details */
     251          78 :   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          78 :   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          78 :   return wksp;
     264          78 : }
     265             : 
     266             : void
     267          66 : fd_wksp_delete_anon( fd_wksp_t * wksp ) {
     268          66 :   fd_shmem_join_info_t info[1];
     269          66 :   if( FD_UNLIKELY( fd_shmem_leave_anonymous( wksp, info ) ) ) return; /* logs details */
     270          60 :   fd_shmem_release( fd_wksp_delete( fd_wksp_leave( wksp ) ), info->page_sz, info->page_cnt ); /* logs details */
     271          60 : }
     272             : 
     273             : fd_wksp_t *
     274        2412 : fd_wksp_attach( char const * name ) {
     275        2412 :   return (fd_wksp_t *)
     276        2412 :     fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, fd_wksp_private_join_func, NULL, NULL ); /* logs details */
     277        2412 : }
     278             : 
     279             : int
     280        2178 : fd_wksp_detach( fd_wksp_t * wksp ) {
     281        2178 :   if( FD_UNLIKELY( !wksp ) ) {
     282           3 :     FD_LOG_WARNING(( "NULL wksp" ));
     283           3 :     return 1;
     284           3 :   }
     285        2175 :   return fd_shmem_leave( wksp, fd_wksp_private_leave_func, NULL ); /* logs details */
     286        2178 : }
     287             : 
     288             : fd_wksp_t *
     289         441 : fd_wksp_containing( void const * laddr ) {
     290         441 :   if( FD_UNLIKELY( !laddr ) ) return NULL;
     291             : 
     292         426 :   fd_shmem_join_info_t info[1];
     293         426 :   if( FD_UNLIKELY( fd_shmem_join_query_by_addr( laddr, 1UL, info ) ) ) return NULL;
     294             : 
     295         381 :   fd_wksp_t * wksp = (fd_wksp_t *)info->join;
     296         381 :   if( FD_UNLIKELY( !wksp ) ) return NULL;
     297             : 
     298         381 :   if( FD_UNLIKELY( wksp->magic!=FD_WKSP_MAGIC ) ) return NULL;
     299             : 
     300         381 :   return wksp;
     301         381 : }
     302             : 
     303             : void *
     304             : fd_wksp_alloc_laddr( fd_wksp_t * wksp,
     305             :                      ulong       align,
     306             :                      ulong       sz,
     307         213 :                      ulong       tag ) {
     308         213 :   ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
     309         213 :   if( FD_UNLIKELY( !gaddr ) ) return NULL;
     310         189 :   return fd_wksp_laddr_fast( wksp, gaddr );
     311         213 : }
     312             : 
     313             : void
     314         165 : fd_wksp_free_laddr( void * laddr ) {
     315         165 :   if( FD_UNLIKELY( !laddr ) ) return;
     316             : 
     317         159 :   fd_wksp_t * wksp = fd_wksp_containing( laddr );
     318         159 :   if( FD_UNLIKELY( !wksp ) ) {
     319          12 :     FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
     320          12 :     return;
     321          12 :   }
     322             : 
     323         147 :   ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
     324         147 :   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         147 :   fd_wksp_free( wksp, gaddr );
     330         147 : }
     331             : 
     332             : /* cstr helper APIs ***************************************************/
     333             : 
     334             : char *
     335             : fd_wksp_cstr( fd_wksp_t const * wksp,
     336             :               ulong             gaddr,
     337         177 :               char *            cstr ) {
     338         177 :   if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
     339         171 :   if( FD_UNLIKELY( !wksp ) ) { FD_LOG_WARNING(( "NULL wksp" )); return NULL; }
     340             : 
     341         165 :   if( FD_UNLIKELY( !( (!gaddr) | ((wksp->gaddr_lo<=gaddr) & (gaddr<=wksp->gaddr_hi)) ) ) ) {
     342           6 :     FD_LOG_WARNING(( "unmappable gaddr" ));
     343           6 :     return NULL;
     344           6 :   }
     345             : 
     346         159 :   return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
     347         165 : }
     348             : 
     349             : char *
     350             : fd_wksp_cstr_laddr( void const * laddr,
     351          33 :                     char *       cstr ) {
     352          33 :   if( FD_UNLIKELY( !cstr ) ) { FD_LOG_WARNING(( "NULL cstr" )); return NULL; }
     353             : 
     354          27 :   fd_wksp_t const * wksp = fd_wksp_containing( laddr );
     355          27 :   if( FD_UNLIKELY( !wksp ) ) {
     356          12 :     FD_LOG_WARNING(( "laddr does not appear to be from a workspace" ));
     357          12 :     return NULL;
     358          12 :   }
     359             : 
     360          15 :   ulong gaddr = fd_wksp_gaddr_fast( wksp, laddr );
     361          15 :   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          15 :   return fd_wksp_private_cstr( wksp->name, gaddr, cstr );
     367          15 : }
     368             : 
     369             : char *
     370             : fd_wksp_cstr_alloc( char const * name,
     371             :                     ulong        align,
     372             :                     ulong        sz,
     373             :                     ulong        tag,
     374         117 :                     char *       cstr ) {
     375         117 :   if( FD_UNLIKELY( !cstr ) ) {
     376           0 :     FD_LOG_WARNING(( "NULL cstr" ));
     377           0 :     return NULL;
     378           0 :   }
     379             : 
     380         117 :   fd_wksp_t * wksp = fd_wksp_attach( name );
     381         117 :   if( FD_UNLIKELY( !wksp ) ) return NULL; /* logs details */
     382             :   /* name must be valid at this point */
     383             : 
     384         108 :   ulong gaddr = fd_wksp_alloc( wksp, align, sz, tag );
     385         108 :   if( FD_UNLIKELY( (!!sz) & (!gaddr) ) ) {
     386          24 :     fd_wksp_detach( wksp ); /* logs details */
     387          24 :     return NULL;
     388          24 :   }
     389             : 
     390          84 :   fd_wksp_detach( wksp ); /* logs details */
     391          84 :   return fd_wksp_private_cstr( name, gaddr, cstr );
     392         108 : }
     393             : 
     394             : void
     395          75 : fd_wksp_cstr_free( char const * cstr ) {
     396          75 :   char  name[ FD_SHMEM_NAME_MAX ];
     397          75 :   ulong gaddr;
     398          75 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
     399             : 
     400          57 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     401          57 :   if( FD_UNLIKELY( !wksp ) ) return;
     402             : 
     403          57 :   fd_wksp_free( wksp, gaddr ); /* logs details */
     404             : 
     405          57 :   fd_wksp_detach( wksp ); /* logs details */
     406          57 : }
     407             : 
     408             : ulong
     409          78 : fd_wksp_cstr_tag( char const * cstr ) {
     410          78 :   char  name[ FD_SHMEM_NAME_MAX ];
     411          78 :   ulong gaddr;
     412          78 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return 0UL; /* logs details */
     413             : 
     414          60 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     415          60 :   if( FD_UNLIKELY( !wksp ) ) return 0UL;
     416             : 
     417          60 :   ulong tag = fd_wksp_tag( wksp, gaddr ); /* logs details */
     418             : 
     419          60 :   fd_wksp_detach( wksp ); /* logs details */
     420             : 
     421          60 :   return tag;
     422          60 : }
     423             : 
     424             : void
     425             : fd_wksp_cstr_memset( char const * cstr,
     426          42 :                      int          c ) {
     427          42 :   char  name[ FD_SHMEM_NAME_MAX ];
     428          42 :   ulong gaddr;
     429          42 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return; /* logs details */
     430             : 
     431          18 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     432          18 :   if( FD_UNLIKELY( !wksp ) ) return;
     433             : 
     434          18 :   fd_wksp_memset( wksp, gaddr, c ); /* logs details */
     435             : 
     436          18 :   fd_wksp_detach( wksp ); /* logs details */
     437          18 : }
     438             : 
     439             : void *
     440        1158 : fd_wksp_map( char const * cstr ) {
     441        1158 :   char  name[ FD_SHMEM_NAME_MAX ];
     442        1158 :   ulong gaddr;
     443        1158 :   if( FD_UNLIKELY( !fd_wksp_private_cstr_parse( cstr, name, &gaddr ) ) ) return NULL; /* logs details */
     444             : 
     445        1047 :   fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
     446        1047 :   if( FD_UNLIKELY( !wksp ) ) return NULL;
     447             : 
     448        1047 :   void * laddr = fd_wksp_laddr( wksp, gaddr ); /* logs details */
     449        1047 :   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           3 :     fd_wksp_detach( wksp ); /* logs details */
     454           3 :     return NULL;
     455           3 :   }
     456             : 
     457        1044 :   return laddr;
     458        1047 : }
     459             : 
     460             : void
     461         999 : fd_wksp_unmap( void const * laddr ) {
     462         999 :   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         993 :   fd_shmem_join_info_t info[1];
     469         993 :   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         993 :   fd_wksp_t * wksp = (fd_wksp_t *)info->join;
     475         993 :   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         993 :   fd_wksp_detach( wksp ); /* logs details */
     481         993 : }
     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