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: 2024-11-13 11:58:15 Functions: 22 26 84.6 %

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

Generated by: LCOV version 1.14