LCOV - code coverage report
Current view: top level - util/shmem - fd_shmem_admin.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 301 459 65.6 %
Date: 2025-03-20 12:08:36 Functions: 16 19 84.2 %

          Line data    Source code
       1             : #if FD_HAS_THREADS /* THREADS implies HOSTED */
       2             : #define _GNU_SOURCE
       3             : #endif
       4             : 
       5             : #include "fd_shmem_private.h"
       6             : 
       7             : /* Portable APIs */
       8             : 
       9             : int
      10           0 : fd_cstr_to_shmem_lg_page_sz( char const * cstr ) {
      11           0 :   if( !cstr ) return FD_SHMEM_UNKNOWN_LG_PAGE_SZ;
      12             : 
      13           0 :   if( !fd_cstr_casecmp( cstr, "normal"   ) ) return FD_SHMEM_NORMAL_LG_PAGE_SZ;
      14           0 :   if( !fd_cstr_casecmp( cstr, "huge"     ) ) return FD_SHMEM_HUGE_LG_PAGE_SZ;
      15           0 :   if( !fd_cstr_casecmp( cstr, "gigantic" ) ) return FD_SHMEM_GIGANTIC_LG_PAGE_SZ;
      16             : 
      17           0 :   int i = fd_cstr_to_int( cstr );
      18           0 :   if( i==FD_SHMEM_NORMAL_LG_PAGE_SZ   ) return FD_SHMEM_NORMAL_LG_PAGE_SZ;
      19           0 :   if( i==FD_SHMEM_HUGE_LG_PAGE_SZ     ) return FD_SHMEM_HUGE_LG_PAGE_SZ;
      20           0 :   if( i==FD_SHMEM_GIGANTIC_LG_PAGE_SZ ) return FD_SHMEM_GIGANTIC_LG_PAGE_SZ;
      21             : 
      22           0 :   return FD_SHMEM_UNKNOWN_LG_PAGE_SZ;
      23           0 : }
      24             : 
      25             : char const *
      26           0 : fd_shmem_lg_page_sz_to_cstr( int lg_page_sz ) {
      27           0 :   switch( lg_page_sz ) {
      28           0 :   case FD_SHMEM_NORMAL_LG_PAGE_SZ:   return "normal";
      29           0 :   case FD_SHMEM_HUGE_LG_PAGE_SZ:     return "huge";
      30           0 :   case FD_SHMEM_GIGANTIC_LG_PAGE_SZ: return "gigantic";
      31           0 :   default:                           break;
      32           0 :   }
      33           0 :   return "unknown";
      34           0 : }
      35             : 
      36             : ulong
      37         219 : fd_cstr_to_shmem_page_sz( char const * cstr ) {
      38         219 :   if( !cstr ) return FD_SHMEM_UNKNOWN_PAGE_SZ;
      39             : 
      40         219 :   if( !fd_cstr_casecmp( cstr, "normal"   ) ) return FD_SHMEM_NORMAL_PAGE_SZ;
      41         159 :   if( !fd_cstr_casecmp( cstr, "huge"     ) ) return FD_SHMEM_HUGE_PAGE_SZ;
      42         159 :   if( !fd_cstr_casecmp( cstr, "gigantic" ) ) return FD_SHMEM_GIGANTIC_PAGE_SZ;
      43             : 
      44           9 :   ulong u = fd_cstr_to_ulong( cstr );
      45           9 :   if( u==FD_SHMEM_NORMAL_PAGE_SZ   ) return FD_SHMEM_NORMAL_PAGE_SZ;
      46           9 :   if( u==FD_SHMEM_HUGE_PAGE_SZ     ) return FD_SHMEM_HUGE_PAGE_SZ;
      47           9 :   if( u==FD_SHMEM_GIGANTIC_PAGE_SZ ) return FD_SHMEM_GIGANTIC_PAGE_SZ;
      48             : 
      49           9 :   return FD_SHMEM_UNKNOWN_PAGE_SZ;
      50           9 : }
      51             : 
      52             : char const *
      53        4209 : fd_shmem_page_sz_to_cstr( ulong page_sz ) {
      54        4209 :   switch( page_sz ) {
      55         120 :   case FD_SHMEM_NORMAL_PAGE_SZ:   return "normal";
      56         117 :   case FD_SHMEM_HUGE_PAGE_SZ:     return "huge";
      57        3972 :   case FD_SHMEM_GIGANTIC_PAGE_SZ: return "gigantic";
      58           0 :   default:                        break;
      59        4209 :   }
      60           0 :   return "unknown";
      61        4209 : }
      62             : 
      63             : #if FD_HAS_HOSTED
      64             : 
      65             : #include <ctype.h>
      66             : #include <errno.h>
      67             : #include <unistd.h>
      68             : #include <fcntl.h>
      69             : #include <linux/mempolicy.h>
      70             : #include <sys/mman.h>
      71             : #include <sys/stat.h>
      72             : #include <linux/mman.h>
      73             : 
      74             : #if FD_HAS_THREADS
      75             : pthread_mutex_t fd_shmem_private_lock[1];
      76             : #endif
      77             : 
      78             : char  fd_shmem_private_base[ FD_SHMEM_PRIVATE_BASE_MAX ]; /* ""  at thread group start, initialized at boot */
      79             : ulong fd_shmem_private_base_len;                          /* 0UL at ",                  initialized at boot */
      80             : 
      81             : /* NUMA TOPOLOGY APIS *************************************************/
      82             : 
      83             : static ulong  fd_shmem_private_numa_cnt;                      /* 0UL at thread group start, initialized at boot */
      84             : static ulong  fd_shmem_private_cpu_cnt;                       /* " */
      85             : static ushort fd_shmem_private_numa_idx[ FD_SHMEM_CPU_MAX  ]; /* " */
      86             : static ushort fd_shmem_private_cpu_idx [ FD_SHMEM_NUMA_MAX ]; /* " */
      87             : 
      88           6 : ulong fd_shmem_numa_cnt( void ) { return fd_shmem_private_numa_cnt; }
      89         300 : ulong fd_shmem_cpu_cnt ( void ) { return fd_shmem_private_cpu_cnt;  }
      90             : 
      91             : ulong
      92         267 : fd_shmem_numa_idx( ulong cpu_idx ) {
      93         267 :   if( FD_UNLIKELY( cpu_idx>=fd_shmem_private_cpu_cnt ) ) return ULONG_MAX;
      94         267 :   return (ulong)fd_shmem_private_numa_idx[ cpu_idx ];
      95         267 : }
      96             : 
      97             : ulong
      98          30 : fd_shmem_cpu_idx( ulong numa_idx ) {
      99          30 :   if( FD_UNLIKELY( numa_idx>=fd_shmem_private_numa_cnt ) ) return ULONG_MAX;
     100          30 :   return (ulong)fd_shmem_private_cpu_idx[ numa_idx ];
     101          30 : }
     102             : 
     103             : int
     104             : fd_shmem_numa_validate( void const * mem,
     105             :                         ulong        page_sz,
     106             :                         ulong        page_cnt,
     107          99 :                         ulong        cpu_idx ) {
     108          99 :   if( FD_UNLIKELY( !mem ) ) {
     109           0 :     FD_LOG_WARNING(( "NULL mem" ));
     110           0 :     return EINVAL;
     111           0 :   }
     112             : 
     113          99 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) {
     114           0 :     FD_LOG_WARNING(( "bad page_sz (%lu)", page_sz ));
     115           0 :     return EINVAL;
     116           0 :   }
     117             : 
     118          99 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, page_sz ) ) ) {
     119           0 :     FD_LOG_WARNING(( "misaligned mem" ));
     120           0 :     return EINVAL;
     121           0 :   }
     122             : 
     123          99 :   if( FD_UNLIKELY( !((1UL<=page_cnt) & (page_cnt<=(((ulong)LONG_MAX)/page_sz))) ) ) {
     124           0 :     FD_LOG_WARNING(( "bad page_cnt (%lu)", page_cnt ));
     125           0 :     return EINVAL;
     126           0 :   }
     127             : 
     128          99 :   if( FD_UNLIKELY( !(cpu_idx<fd_shmem_cpu_cnt()) ) ) {
     129           0 :     FD_LOG_WARNING(( "bad cpu_idx (%lu)", cpu_idx ));
     130           0 :     return EINVAL;
     131           0 :   }
     132             : 
     133          99 :   ulong numa_idx = fd_shmem_numa_idx( cpu_idx );
     134             : 
     135          99 :   ulong   page = (ulong)mem;
     136          99 :   int     batch_status[ 512 ];
     137          99 :   void *  batch_page  [ 512 ];
     138          99 :   ulong   batch_cnt = 0UL;
     139         249 :   while( page_cnt ) {
     140         150 :     batch_page[ batch_cnt++ ] = (void *)page;
     141         150 :     page += page_sz;
     142         150 :     page_cnt--;
     143         150 :     if( FD_UNLIKELY( ((batch_cnt==512UL) | (!page_cnt) ) ) ) {
     144          99 :       if( FD_UNLIKELY( fd_numa_move_pages( 0, batch_cnt, batch_page, NULL, batch_status, 0 ) ) ) {
     145           0 :         FD_LOG_WARNING(( "fd_numa_move_pages query failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     146           0 :         return errno;
     147           0 :       }
     148         249 :       for( ulong batch_idx=0UL; batch_idx<batch_cnt; batch_idx++ ) {
     149         150 :         if( FD_UNLIKELY( batch_status[batch_idx]<0 ) ) {
     150           0 :           int err = -batch_status[batch_idx];
     151           0 :           FD_LOG_WARNING(( "page status failed (%i-%s)", err, fd_io_strerror( err ) ));
     152           0 :           return err;
     153           0 :         }
     154         150 :         if( FD_UNLIKELY( batch_status[batch_idx]!=(int)numa_idx ) ) {
     155           0 :           FD_LOG_WARNING(( "page allocated to numa %i instead of numa %lu", batch_status[batch_idx], numa_idx ));
     156           0 :           return EFAULT;
     157           0 :         }
     158         150 :       }
     159          99 :       batch_cnt = 0UL;
     160          99 :     }
     161         150 :   }
     162             : 
     163          99 :   return 0;
     164          99 : }
     165             : 
     166             : /* SHMEM REGION CREATION AND DESTRUCTION ******************************/
     167             : 
     168             : static int
     169             : fd_shmem_create_multi_flags( char const *  name,
     170             :                              ulong         page_sz,
     171             :                              ulong         sub_cnt,
     172             :                              ulong const * _sub_page_cnt,
     173             :                              ulong const * _sub_cpu_idx,
     174             :                              ulong         mode,
     175          63 :                              int           open_flags ) {
     176             : 
     177             :   /* Check input args */
     178             : 
     179          63 :   if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name (%s)", name ? name : "NULL" )); return EINVAL; }
     180             : 
     181          60 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "bad page_sz (%lu)", page_sz )); return EINVAL; }
     182             : 
     183          57 :   if( FD_UNLIKELY( !sub_cnt       ) ) { FD_LOG_WARNING(( "zero sub_cnt"      )); return EINVAL; }
     184          57 :   if( FD_UNLIKELY( !_sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return EINVAL; }
     185          57 :   if( FD_UNLIKELY( !_sub_cpu_idx  ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx"  )); return EINVAL; }
     186             : 
     187          57 :   ulong cpu_cnt = fd_shmem_cpu_cnt();
     188             : 
     189          57 :   ulong page_cnt = 0UL;
     190         105 :   for( ulong sub_idx=0UL; sub_idx<sub_cnt; sub_idx++ ) {
     191          57 :     ulong sub_page_cnt = _sub_page_cnt[ sub_idx ];
     192          57 :     if( FD_UNLIKELY( !sub_page_cnt ) ) continue; /* Skip over empty subregions */
     193             : 
     194          54 :     page_cnt += sub_page_cnt;
     195          54 :     if( FD_UNLIKELY( page_cnt<sub_page_cnt ) ) {
     196           0 :       FD_LOG_WARNING(( "sub[%lu] sub page_cnt overflow (page_cnt %lu, sub_page_cnt %lu)",
     197           0 :                        sub_idx, page_cnt-sub_page_cnt, sub_page_cnt ));
     198           0 :       return EINVAL;
     199           0 :     }
     200             : 
     201          54 :     ulong sub_cpu_idx = _sub_cpu_idx[ sub_idx ];
     202          54 :     if( FD_UNLIKELY( sub_cpu_idx>=cpu_cnt ) ) {
     203           9 :       FD_LOG_WARNING(( "sub[%lu] bad cpu_idx (%lu)", sub_idx, sub_cpu_idx ));
     204           9 :       return EINVAL;
     205           9 :     }
     206          54 :   }
     207             : 
     208          48 :   if( FD_UNLIKELY( !((1UL<=page_cnt) & (page_cnt<=(((ulong)LONG_MAX)/page_sz))) ) ) { /* LONG_MAX from off_t */
     209           3 :     FD_LOG_WARNING(( "bad total page_cnt (%lu)", page_cnt ));
     210           3 :     return EINVAL;
     211           3 :   }
     212             : 
     213          45 :   if( FD_UNLIKELY( mode!=(ulong)(mode_t)mode ) ) { FD_LOG_WARNING(( "bad mode (0%03lo)", mode )); return EINVAL; }
     214             : 
     215             :   /* We use the FD_SHMEM_LOCK in create just to be safe given some
     216             :      thread safety ambiguities in the documentation for some of the
     217             :      below APIs. */
     218             : 
     219          36 :   FD_SHMEM_LOCK;
     220             : 
     221          36 :   int err;
     222             : 
     223          36 : # define ERROR( cleanup ) do { err = errno; goto cleanup; } while(0)
     224             : 
     225          36 :   int    orig_mempolicy;
     226          36 :   ulong  orig_nodemask[ (FD_SHMEM_NUMA_MAX+63UL)/64UL ];
     227          36 :   char   path[ FD_SHMEM_PRIVATE_PATH_BUF_MAX ];
     228          36 :   int    fd;
     229          36 :   void * shmem;
     230             : 
     231          36 :   ulong  sz = page_cnt*page_sz;
     232             : 
     233             :   /* Save this thread's numa node mempolicy */
     234             : 
     235          36 :   if( FD_UNLIKELY( fd_numa_get_mempolicy( &orig_mempolicy, orig_nodemask, FD_SHMEM_NUMA_MAX, NULL, 0UL ) ) ) {
     236           0 :     FD_LOG_WARNING(( "fd_numa_get_mempolicy failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     237           0 :     ERROR( done );
     238           0 :   }
     239             : 
     240             :   /* Create the region */
     241             : 
     242          36 :   fd = open( fd_shmem_private_path( name, page_sz, path ), open_flags, (mode_t)mode );
     243          36 :   if( FD_UNLIKELY( fd==-1 ) ) {
     244           6 :     FD_LOG_WARNING(( "open(\"%s\",%#x,0%03lo) failed (%i-%s)", path, (uint)open_flags, mode, errno, fd_io_strerror( errno ) ));
     245           6 :     ERROR( restore );
     246           6 :   }
     247             : 
     248             :   /* Size the region */
     249             : 
     250          30 :   if( FD_UNLIKELY( ftruncate( fd, (off_t)sz ) ) ) {
     251           0 :     FD_LOG_WARNING(( "ftruncate(\"%s\",%lu KiB) failed (%i-%s)", path, sz>>10, errno, fd_io_strerror( errno ) ));
     252           0 :     ERROR( close );
     253           0 :   }
     254             : 
     255             :   /* Map the region into our address space. */
     256             : 
     257          30 :   shmem = mmap( NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0);
     258          30 :   if( FD_UNLIKELY( shmem==MAP_FAILED ) ) {
     259           0 :     FD_LOG_WARNING(( "mmap(NULL,%lu KiB,PROT_READ|PROT_WRITE,MAP_SHARED,\"%s\",0) failed (%i-%s)",
     260           0 :                      sz>>10, path, errno, fd_io_strerror( errno ) ));
     261           0 :     ERROR( close );
     262           0 :   }
     263             : 
     264             :   /* Validate the mapping */
     265             : 
     266          30 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, page_sz ) ) ) {
     267           0 :     FD_LOG_WARNING(( "misaligned memory mapping for \"%s\"\n\t"
     268           0 :                      "This thread group's hugetlbfs mount path (--shmem-path / FD_SHMEM_PATH):\n\t"
     269           0 :                      "\t%s\n\t"
     270           0 :                      "has probably been corrupted and needs to be redone.\n\t"
     271           0 :                      "See 'bin/fd_shmem_cfg help' for more information.",
     272           0 :                      path, fd_shmem_private_base ));
     273           0 :     errno = EFAULT; /* ENOMEM is arguable */
     274           0 :     ERROR( unmap );
     275           0 :   }
     276             : 
     277             :   /* For each subregion */
     278             : 
     279          30 :   uchar * sub_shmem = (uchar *)shmem;
     280          60 :   for( ulong sub_idx=0UL; sub_idx<sub_cnt; sub_idx++ ) {
     281          30 :     ulong sub_page_cnt = _sub_page_cnt[ sub_idx ];
     282          30 :     if( FD_UNLIKELY( !sub_page_cnt ) ) continue; /* Skip over empty sub-regions */
     283             : 
     284          30 :     ulong sub_sz       = sub_page_cnt*page_sz;
     285          30 :     ulong sub_cpu_idx  = _sub_cpu_idx[ sub_idx ];
     286          30 :     ulong sub_numa_idx = fd_shmem_numa_idx( sub_cpu_idx );
     287             : 
     288          30 :     ulong nodemask[ (FD_SHMEM_NUMA_MAX+63UL)/64UL ];
     289             : 
     290             :     /* Set the mempolicy to bind newly allocated memory to the numa idx
     291             :        corresponding to logical cpu cpu_idx.  This should force page
     292             :        allocation to be on the desired numa node, keeping our fingers
     293             :        crossed that even the ftruncate / mmap above did not trigger
     294             :        this; it doesn't seem too, even when the user's thread group has
     295             :        configured things like mlockall(MCL_CURRENT | MCL_FUTURE ).
     296             :        Theoretically, the fd_numa_mbind below should do it without this
     297             :        but the Linux kernel tends to view requests to move pages between
     298             :        numa nodes after allocation as for entertainment purposes only. */
     299             : 
     300          30 :     fd_memset( nodemask, 0, 8UL*((FD_SHMEM_NUMA_MAX+63UL)/64UL) );
     301          30 :     nodemask[ sub_numa_idx >> 6 ] = 1UL << (sub_numa_idx & 63UL);
     302             : 
     303          30 :     if( FD_UNLIKELY( fd_numa_set_mempolicy( MPOL_BIND | MPOL_F_STATIC_NODES, nodemask, FD_SHMEM_NUMA_MAX ) ) ) {
     304           0 :       FD_LOG_WARNING(( "fd_numa_set_mempolicy failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     305           0 :       ERROR( unmap );
     306           0 :     }
     307             : 
     308             :     /* If a mempolicy has been set and the numa_idx node does not have
     309             :        sufficient pages to back the mapping, touching the memory will
     310             :        trigger a SIGBUS when it touches the first part of the mapping
     311             :        for which there are no pages.  Unfortunately, mmap will only
     312             :        error if there are insufficient pages across all NUMA nodes (even
     313             :        if using mlockall( MCL_FUTURE ) or passing MAP_POPULATE), so we
     314             :        need to check that the mapping can be backed without handling
     315             :        signals.
     316             : 
     317             :        So we mlock the subregion to force the region to be backed by
     318             :        pages now.  The subregion should be backed by page_sz pages
     319             :        (thanks to the hugetlbfs configuration) and should be on the
     320             :        correct NUMA node (thanks to the mempolicy above).  Specifically,
     321             :        mlock will error with ENOMEM if there were insufficient pages
     322             :        available.  mlock guarantees that if it succeeds, the mapping has
     323             :        been fully backed by pages and these pages will remain resident
     324             :        in DRAM at least until the mapping is closed.  We can then
     325             :        proceed as usual without the risk of meeting SIGBUS or its
     326             :        friends. */
     327             : 
     328          30 :     if( FD_UNLIKELY( fd_numa_mlock( sub_shmem, sub_sz ) ) ) {
     329           0 :       FD_LOG_WARNING(( "sub[%lu]: fd_numa_mlock(\"%s\",%lu KiB) failed (%i-%s)",
     330           0 :                        sub_idx, path, sub_sz>>10, errno, fd_io_strerror( errno ) ));
     331           0 :       ERROR( unmap );
     332           0 :     }
     333             : 
     334             :     /* At this point all pages in this subregion should be allocated on
     335             :        the right NUMA node and resident in DRAM.  But in the spirit of
     336             :        not trusting Linux to get this right robustly, we continue with
     337             :        touching pages from cpu_idx. */
     338             : 
     339             :     /* FIXME: NUMA TOUCH HERE (ALSO WOULD A LOCAL TOUCH WORK GIVEN THE
     340             :        MEMPOLICY DONE ABOVE?) */
     341             : 
     342             :     /* fd_numa_mbind the memory subregion to this numa node to nominally
     343             :        stay put after we unmap it.  We recompute the nodemask to be on
     344             :        the safe side in case set mempolicy above clobbered it. */
     345             : 
     346          30 :     fd_memset( nodemask, 0, 8UL*((FD_SHMEM_NUMA_MAX+63UL)/64UL) );
     347          30 :     nodemask[ sub_numa_idx >> 6 ] = 1UL << (sub_numa_idx & 63UL);
     348             : 
     349          30 :     if( FD_UNLIKELY( fd_numa_mbind( sub_shmem, sub_sz, MPOL_BIND, nodemask, FD_SHMEM_NUMA_MAX, MPOL_MF_MOVE|MPOL_MF_STRICT ) ) ) {
     350           0 :       FD_LOG_WARNING(( "sub[%lu]: fd_numa_mbind(\"%s\",%lu KiB,MPOL_BIND,1UL<<%lu,MPOL_MF_MOVE|MPOL_MF_STRICT) failed (%i-%s)",
     351           0 :                        sub_idx, path, sub_sz>>10, sub_numa_idx, errno, fd_io_strerror( errno ) ));
     352           0 :       ERROR( unmap );
     353           0 :     }
     354             : 
     355             :     /* And since the fd_numa_mbind still often will ignore requests, we
     356             :        double check that the pages are in the right place. */
     357             : 
     358          30 :     int warn = fd_shmem_numa_validate( sub_shmem, page_sz, sub_page_cnt, sub_cpu_idx ); /* logs details */
     359          30 :     if( FD_UNLIKELY( warn ) )
     360           0 :       FD_LOG_WARNING(( "sub[%lu]: mmap(NULL,%lu KiB,PROT_READ|PROT_WRITE,MAP_SHARED,\"%s\",0) numa binding failed (%i-%s)",
     361          30 :                        sub_idx, sub_sz>>10, path, warn, fd_io_strerror( warn ) ));
     362             : 
     363          30 :     sub_shmem += sub_sz;
     364          30 :   }
     365             : 
     366          30 :   err = 0;
     367             : 
     368          30 : # undef ERROR
     369             : 
     370          30 : unmap:
     371          30 :   if( FD_UNLIKELY( munmap( shmem, sz ) ) )
     372           0 :     FD_LOG_ERR(( "munmap(\"%s\",%lu KiB) failed (%i-%s)",
     373          30 :                  path, sz>>10, errno, fd_io_strerror( errno ) ));
     374             : 
     375          30 : close:
     376          30 :   if( FD_UNLIKELY( err ) && FD_UNLIKELY( unlink( path ) ) )
     377           0 :     FD_LOG_ERR(( "unlink(\"%s\") failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
     378          30 :   if( FD_UNLIKELY( close( fd ) ) )
     379           0 :     FD_LOG_ERR(( "close(\"%s\") failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
     380             : 
     381          36 : restore:
     382          36 :   if( FD_UNLIKELY( fd_numa_set_mempolicy( orig_mempolicy, orig_nodemask, FD_SHMEM_NUMA_MAX ) ) )
     383           0 :     FD_LOG_ERR(( "fd_numa_set_mempolicy failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     384             : 
     385          36 : done:
     386          36 :   FD_SHMEM_UNLOCK;
     387          36 :   return err;
     388          36 : }
     389             : 
     390             : int
     391             : fd_shmem_create_multi( char const *  name,
     392             :                        ulong         page_sz,
     393             :                        ulong         sub_cnt,
     394             :                        ulong const * _sub_page_cnt,
     395             :                        ulong const * _sub_cpu_idx,
     396          63 :                        ulong         mode ) {
     397          63 :   return fd_shmem_create_multi_flags( name, page_sz, sub_cnt, _sub_page_cnt, _sub_cpu_idx, mode, O_RDWR | O_CREAT | O_EXCL );
     398          63 : }
     399             : 
     400             : int
     401             : fd_shmem_update_multi( char const *  name,
     402             :                        ulong         page_sz,
     403             :                        ulong         sub_cnt,
     404             :                        ulong const * _sub_page_cnt,
     405             :                        ulong const * _sub_cpu_idx,
     406           0 :                        ulong         mode ) {
     407           0 :   return fd_shmem_create_multi_flags( name, page_sz, sub_cnt, _sub_page_cnt, _sub_cpu_idx, mode, O_RDWR );
     408           0 : }
     409             : 
     410             : int
     411             : fd_shmem_unlink( char const * name,
     412          30 :                  ulong        page_sz ) {
     413          30 :   char path[ FD_SHMEM_PRIVATE_PATH_BUF_MAX ];
     414             : 
     415             :   /* Check input args */
     416             : 
     417          30 :   if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name (%s)", name ? name : "NULL" )); return EINVAL; }
     418             : 
     419          30 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "bad page_sz (%lu)", page_sz )); return EINVAL; }
     420             : 
     421             :   /* Unlink the name */
     422             : 
     423          30 :   if( FD_UNLIKELY( unlink( fd_shmem_private_path( name, page_sz, path ) ) ) ) {
     424           0 :     FD_LOG_WARNING(( "unlink(\"%s\") failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
     425           0 :     return errno;
     426           0 :   }
     427             : 
     428          30 :   return 0;
     429          30 : }
     430             : 
     431             : int
     432             : fd_shmem_info( char const *      name,
     433             :                ulong             page_sz,
     434        4260 :                fd_shmem_info_t * opt_info ) {
     435             : 
     436        4260 :   if( FD_UNLIKELY( !fd_shmem_name_len( name ) ) ) { FD_LOG_WARNING(( "bad name (%s)", name ? name : "NULL" )); return EINVAL; }
     437             : 
     438        4260 :   if( !page_sz ) {
     439        2013 :     if( !fd_shmem_info( name, FD_SHMEM_GIGANTIC_PAGE_SZ, opt_info ) ) return 0;
     440         117 :     if( !fd_shmem_info( name, FD_SHMEM_HUGE_PAGE_SZ,     opt_info ) ) return 0;
     441         117 :     if( !fd_shmem_info( name, FD_SHMEM_NORMAL_PAGE_SZ,   opt_info ) ) return 0;
     442         117 :     return ENOENT;
     443         117 :   }
     444             : 
     445        2247 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "bad page_sz (%lu)", page_sz )); return EINVAL; }
     446             : 
     447        2247 :   char path[ FD_SHMEM_PRIVATE_PATH_BUF_MAX ];
     448        2247 :   int  fd = open( fd_shmem_private_path( name, page_sz, path ), O_RDONLY, (mode_t)0 );
     449        2247 :   if( FD_UNLIKELY( fd==-1 ) ) return errno; /* no logging here as this might be an existence check */
     450             : 
     451        1896 :   struct stat stat[1];
     452        1896 :   if( FD_UNLIKELY( fstat( fd, stat ) ) ) {
     453           0 :     FD_LOG_WARNING(( "fstat failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     454           0 :     int err = errno;
     455           0 :     if( FD_UNLIKELY( close( fd ) ) )
     456           0 :       FD_LOG_WARNING(( "close(\"%s\") failed (%i-%s); attempting to continue", path, errno, fd_io_strerror( errno ) ));
     457           0 :     return err;
     458           0 :   }
     459             : 
     460        1896 :   ulong sz = (ulong)stat->st_size;
     461        1896 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( sz, page_sz ) ) ) {
     462           0 :     FD_LOG_WARNING(( "\"%s\" size (%lu) not a page size (%lu) multiple\n\t"
     463           0 :                      "This thread group's hugetlbfs mount path (--shmem-path / FD_SHMEM_PATH):\n\t"
     464           0 :                      "\t%s\n\t"
     465           0 :                      "has probably been corrupted and needs to be redone.\n\t"
     466           0 :                      "See 'bin/fd_shmem_cfg help' for more information.",
     467           0 :                      path, sz, page_sz, fd_shmem_private_base ));
     468           0 :     if( FD_UNLIKELY( close( fd ) ) )
     469           0 :       FD_LOG_WARNING(( "close(\"%s\") failed (%i-%s); attempting to continue", path, errno, fd_io_strerror( errno ) ));
     470           0 :     return EFAULT;
     471           0 :   }
     472        1896 :   ulong page_cnt = sz / page_sz;
     473             : 
     474        1896 :   if( FD_UNLIKELY( close( fd ) ) )
     475           0 :     FD_LOG_WARNING(( "close(\"%s\") failed (%i-%s); attempting to continue", path, errno, fd_io_strerror( errno ) ));
     476             : 
     477        1896 :   if( opt_info ) {
     478        1896 :     opt_info->page_sz  = page_sz;
     479        1896 :     opt_info->page_cnt = page_cnt;
     480        1896 :   }
     481        1896 :   return 0;
     482        1896 : }
     483             : 
     484             : /* RAW PAGE ALLOCATION APIS *******************************************/
     485             : 
     486             : void *
     487             : fd_shmem_acquire_multi( ulong         page_sz,
     488             :                         ulong         sub_cnt,
     489             :                         ulong const * _sub_page_cnt,
     490         108 :                         ulong const * _sub_cpu_idx ) {
     491             : 
     492             :   /* Check input args */
     493             : 
     494         108 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) { FD_LOG_WARNING(( "bad page_sz (%lu)", page_sz )); return NULL; }
     495             : 
     496         108 :   if( FD_UNLIKELY( !sub_cnt       ) ) { FD_LOG_WARNING(( "zero sub_cnt"      )); return NULL; }
     497         108 :   if( FD_UNLIKELY( !_sub_page_cnt ) ) { FD_LOG_WARNING(( "NULL sub_page_cnt" )); return NULL; }
     498         108 :   if( FD_UNLIKELY( !_sub_cpu_idx  ) ) { FD_LOG_WARNING(( "NULL sub_cpu_idx"  )); return NULL; }
     499             : 
     500         108 :   ulong cpu_cnt = fd_shmem_cpu_cnt();
     501             : 
     502         108 :   ulong page_cnt = 0UL;
     503         213 :   for( ulong sub_idx=0UL; sub_idx<sub_cnt; sub_idx++ ) {
     504         108 :     ulong sub_page_cnt = _sub_page_cnt[ sub_idx ];
     505         108 :     if( FD_UNLIKELY( !sub_page_cnt ) ) continue; /* Skip over empty subregions */
     506             : 
     507         108 :     page_cnt += sub_page_cnt;
     508         108 :     if( FD_UNLIKELY( page_cnt<sub_page_cnt ) ) {
     509           0 :       FD_LOG_WARNING(( "sub[%lu] sub page_cnt overflow (page_cnt %lu, sub_page_cnt %lu)",
     510           0 :                        sub_idx, page_cnt-sub_page_cnt, sub_page_cnt ));
     511           0 :       return NULL;
     512           0 :     }
     513             : 
     514         108 :     ulong sub_cpu_idx = _sub_cpu_idx[ sub_idx ];
     515         108 :     if( FD_UNLIKELY( sub_cpu_idx>=cpu_cnt ) ) {
     516           3 :       FD_LOG_WARNING(( "sub[%lu] bad cpu_idx (%lu)", sub_idx, sub_cpu_idx ));
     517           3 :       return NULL;
     518           3 :     }
     519         108 :   }
     520             : 
     521         105 :   if( FD_UNLIKELY( !((1UL<=page_cnt) & (page_cnt<=(((ulong)LONG_MAX)/page_sz))) ) ) { /* LONG_MAX from off_t */
     522           0 :     FD_LOG_WARNING(( "bad total page_cnt (%lu)", page_cnt ));
     523           0 :     return NULL;
     524           0 :   }
     525             : 
     526         105 :   int flags = MAP_PRIVATE | MAP_ANONYMOUS;
     527         105 :   if( page_sz==FD_SHMEM_HUGE_PAGE_SZ     ) flags |= (int)MAP_HUGETLB | (int)MAP_HUGE_2MB;
     528         105 :   if( page_sz==FD_SHMEM_GIGANTIC_PAGE_SZ ) flags |= (int)MAP_HUGETLB | (int)MAP_HUGE_1GB;
     529             : 
     530             :   /* See fd_shmem_create_multi for details on the locking, mempolicy
     531             :      and what not tricks */
     532             : 
     533         105 :   FD_SHMEM_LOCK;
     534             : 
     535         105 :   int err;
     536             : 
     537         105 : # define ERROR( cleanup ) do { err = errno; goto cleanup; } while(0)
     538             : 
     539         105 :   int    orig_mempolicy;
     540         105 :   ulong  orig_nodemask[ (FD_SHMEM_NUMA_MAX+63UL)/64UL ];
     541         105 :   void * mem = NULL;
     542             : 
     543         105 :   ulong  sz = page_cnt*page_sz;
     544             : 
     545         105 :   if( FD_UNLIKELY( fd_numa_get_mempolicy( &orig_mempolicy, orig_nodemask, FD_SHMEM_NUMA_MAX, NULL, 0UL ) ) ) {
     546           0 :     FD_LOG_WARNING(( "fd_numa_get_mempolicy failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     547           0 :     ERROR( done );
     548           0 :   }
     549             : 
     550         105 :   mem = mmap( NULL, sz, PROT_READ | PROT_WRITE, flags, -1, (off_t)0);
     551         105 :   if( FD_UNLIKELY( mem==MAP_FAILED ) ) {
     552          36 :     FD_LOG_WARNING(( "mmap(NULL,%lu KiB,PROT_READ|PROT_WRITE,%x,-1,0) failed (%i-%s)",
     553          36 :                      sz>>10, (uint)flags, errno, fd_io_strerror( errno ) ));
     554          36 :     ERROR( restore );
     555          36 :   }
     556             : 
     557          69 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, page_sz ) ) ) {
     558           0 :     FD_LOG_WARNING(( "mmap(NULL,%lu KiB,PROT_READ|PROT_WRITE,%x,-1,0) misaligned", sz>>10, (uint)flags ));
     559           0 :     errno = EFAULT; /* ENOMEM is arguable */
     560           0 :     ERROR( unmap );
     561           0 :   }
     562             : 
     563          69 :   uchar * sub_mem = (uchar *)mem;
     564         138 :   for( ulong sub_idx=0UL; sub_idx<sub_cnt; sub_idx++ ) {
     565          69 :     ulong sub_page_cnt = _sub_page_cnt[ sub_idx ];
     566          69 :     if( FD_UNLIKELY( !sub_page_cnt ) ) continue;
     567             : 
     568          69 :     ulong sub_sz       = sub_page_cnt*page_sz;
     569          69 :     ulong sub_cpu_idx  = _sub_cpu_idx[ sub_idx ];
     570          69 :     ulong sub_numa_idx = fd_shmem_numa_idx( sub_cpu_idx );
     571             : 
     572          69 :     ulong nodemask[ (FD_SHMEM_NUMA_MAX+63UL)/64UL ];
     573             : 
     574          69 :     fd_memset( nodemask, 0, 8UL*((FD_SHMEM_NUMA_MAX+63UL)/64UL) );
     575          69 :     nodemask[ sub_numa_idx >> 6 ] = 1UL << (sub_numa_idx & 63UL);
     576             : 
     577          69 :     if( FD_UNLIKELY( fd_numa_set_mempolicy( MPOL_BIND | MPOL_F_STATIC_NODES, nodemask, FD_SHMEM_NUMA_MAX ) ) ) {
     578           0 :       FD_LOG_WARNING(( "fd_numa_set_mempolicy failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     579           0 :       ERROR( unmap );
     580           0 :     }
     581             : 
     582          69 :     if( FD_UNLIKELY( fd_numa_mlock( sub_mem, sub_sz ) ) ) {
     583           0 :       FD_LOG_WARNING(( "sub[%lu]: fd_numa_mlock(anon,%lu KiB) failed (%i-%s)",
     584           0 :                        sub_idx, sub_sz>>10, errno, fd_io_strerror( errno ) ));
     585           0 :       ERROR( unmap );
     586           0 :     }
     587             : 
     588             :     /* FIXME: NUMA TOUCH HERE (ALSO WOULD A LOCAL TOUCH WORK GIVEN THE
     589             :        MEMPOLICY DONE ABOVE?) */
     590             : 
     591          69 :     fd_memset( nodemask, 0, 8UL*((FD_SHMEM_NUMA_MAX+63UL)/64UL) );
     592          69 :     nodemask[ sub_numa_idx >> 6 ] = 1UL << (sub_numa_idx & 63UL);
     593             : 
     594          69 :     if( FD_UNLIKELY( fd_numa_mbind( sub_mem, sub_sz, MPOL_BIND, nodemask, FD_SHMEM_NUMA_MAX, MPOL_MF_MOVE|MPOL_MF_STRICT ) ) ) {
     595           0 :       FD_LOG_WARNING(( "sub[%lu]: fd_numa_mbind(anon,%lu KiB,MPOL_BIND,1UL<<%lu,MPOL_MF_MOVE|MPOL_MF_STRICT) failed (%i-%s)",
     596           0 :                        sub_idx, sub_sz>>10, sub_numa_idx, errno, fd_io_strerror( errno ) ));
     597           0 :       ERROR( unmap );
     598           0 :     }
     599             : 
     600          69 :     int warn = fd_shmem_numa_validate( sub_mem, page_sz, sub_page_cnt, sub_cpu_idx ); /* logs details */
     601          69 :     if( FD_UNLIKELY( warn ) )
     602           0 :       FD_LOG_WARNING(( "sub[%lu]: mmap(NULL,%lu KiB,PROT_READ|PROT_WRITE,%x,-1,0) numa binding failed (%i-%s)",
     603          69 :                        sub_idx, sub_sz>>10, (uint)flags, warn, fd_io_strerror( warn ) ));
     604             : 
     605          69 :     sub_mem += sub_sz;
     606          69 :   }
     607             : 
     608          69 :   err = 0;
     609             : 
     610          69 : # undef ERROR
     611             : 
     612          69 : unmap:
     613          69 :   if( FD_UNLIKELY( err ) && FD_UNLIKELY( munmap( mem, sz ) ) )
     614           0 :     FD_LOG_WARNING(( "munmap(anon,%lu KiB) failed (%i-%s); attempting to continue",
     615          69 :                      sz>>10, errno, fd_io_strerror( errno ) ));
     616             : 
     617         105 : restore:
     618         105 :   if( FD_UNLIKELY( fd_numa_set_mempolicy( orig_mempolicy, orig_nodemask, FD_SHMEM_NUMA_MAX ) ) )
     619           0 :     FD_LOG_WARNING(( "fd_numa_set_mempolicy failed (%i-%s); attempting to continue", errno, fd_io_strerror( errno ) ));
     620             : 
     621         105 : done:
     622         105 :   FD_SHMEM_UNLOCK;
     623         105 :   return err ? NULL : mem;
     624         105 : }
     625             : 
     626             : int
     627             : fd_shmem_release( void * mem,
     628             :                   ulong  page_sz,
     629          60 :                   ulong  page_cnt ) {
     630          60 :   if( FD_UNLIKELY( !mem ) ) {
     631           0 :     FD_LOG_WARNING(( "NULL mem" ));
     632           0 :     return -1;
     633           0 :   }
     634             : 
     635          60 :   if( FD_UNLIKELY( !fd_shmem_is_page_sz( page_sz ) ) ) {
     636           0 :     FD_LOG_WARNING(( "bad page_sz (%lu)", page_sz ));
     637           0 :     return -1;
     638           0 :   }
     639             : 
     640          60 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, page_sz ) ) ) {
     641           0 :     FD_LOG_WARNING(( "misaligned mem" ));
     642           0 :     return -1;
     643           0 :   }
     644             : 
     645          60 :   if( FD_UNLIKELY( !((1UL<=page_cnt) & (page_cnt<=(((ulong)LONG_MAX)/page_sz))) ) ) {
     646           0 :     FD_LOG_WARNING(( "bad page_cnt (%lu)", page_cnt ));
     647           0 :     return -1;
     648           0 :   }
     649             : 
     650          60 :   ulong sz = page_sz*page_cnt;
     651             : 
     652          60 :   int result = munmap( mem, sz );
     653          60 :   if( FD_UNLIKELY( result ) )
     654           0 :     FD_LOG_WARNING(( "munmap(anon,%lu KiB) failed (%i-%s); attempting to continue", sz>>10, errno, fd_io_strerror( errno ) ));
     655             : 
     656          60 :   return result;
     657          60 : }
     658             : 
     659             : /* SHMEM PARSING APIS *************************************************/
     660             : 
     661             : ulong
     662        8478 : fd_shmem_name_len( char const * name ) {
     663        8478 :   if( FD_UNLIKELY( !name ) ) return 0UL; /* NULL name */
     664             : 
     665        8457 :   ulong len = 0UL;
     666      142431 :   while( FD_LIKELY( len<FD_SHMEM_NAME_MAX ) ) {
     667      142431 :     char c = name[len];
     668      142431 :     if( FD_UNLIKELY( !c ) ) break;
     669      134139 :     if( FD_UNLIKELY( !( (!!isalnum( c )) | ((len>0UL) & ((c=='_') | (c=='-') | (c=='.'))) ) ) ) return 0UL; /* Bad character */
     670      133974 :     len++;
     671      133974 :   }
     672             : 
     673        8292 :   if( FD_UNLIKELY( !len                   ) ) return 0UL; /* Name too short (empty string) */
     674        8292 :   if( FD_UNLIKELY( len>=FD_SHMEM_NAME_MAX ) ) return 0UL; /* Name too long */
     675        8292 :   return len;
     676        8292 : }
     677             : 
     678             : /* BOOT/HALT APIs *****************************************************/
     679             : 
     680             : void
     681             : fd_shmem_private_boot( int *    pargc,
     682        2328 :                        char *** pargv ) {
     683        2328 :   FD_LOG_INFO(( "fd_shmem: booting" ));
     684             : 
     685             :   /* Initialize the phtread mutex */
     686             : 
     687        2328 : # if FD_HAS_THREADS
     688        2328 :   pthread_mutexattr_t lockattr[1];
     689             : 
     690        2328 :   if( FD_UNLIKELY( pthread_mutexattr_init( lockattr ) ) )
     691           0 :     FD_LOG_ERR(( "fd_shmem: pthread_mutexattr_init failed" ));
     692             : 
     693        2328 :   if( FD_UNLIKELY( pthread_mutexattr_settype( lockattr, PTHREAD_MUTEX_RECURSIVE ) ) )
     694           0 :     FD_LOG_ERR(( "fd_shmem: pthread_mutexattr_settype failed" ));
     695             : 
     696        2328 :   if( FD_UNLIKELY( pthread_mutex_init( fd_shmem_private_lock, lockattr ) ) )
     697           0 :     FD_LOG_ERR(( "fd_shmem: pthread_mutex_init failed" ));
     698             : 
     699        2328 :   if( FD_UNLIKELY( pthread_mutexattr_destroy( lockattr ) ) )
     700           0 :     FD_LOG_WARNING(( "fd_shmem: pthread_mutexattr_destroy failed; attempting to continue" ));
     701        2328 : # endif /* FD_HAS_THREADS */
     702             : 
     703             :   /* Cache the numa topology for this thread group's host for
     704             :      subsequent fast use by the application. */
     705             : 
     706        2328 :   ulong numa_cnt = fd_numa_node_cnt();
     707        2328 :   if( FD_UNLIKELY( !((1UL<=numa_cnt) & (numa_cnt<=FD_SHMEM_NUMA_MAX)) ) )
     708           0 :     FD_LOG_ERR(( "fd_shmem: unexpected numa_cnt %lu (expected in [1,%lu])", numa_cnt, FD_SHMEM_NUMA_MAX ));
     709        2328 :   fd_shmem_private_numa_cnt = numa_cnt;
     710             : 
     711        2328 :   ulong cpu_cnt = fd_numa_cpu_cnt();
     712        2328 :   if( FD_UNLIKELY( !((1UL<=cpu_cnt) & (cpu_cnt<=FD_SHMEM_CPU_MAX)) ) )
     713           0 :     FD_LOG_ERR(( "fd_shmem: unexpected cpu_cnt %lu (expected in [1,%lu])", cpu_cnt, FD_SHMEM_CPU_MAX ));
     714        2328 :   fd_shmem_private_cpu_cnt = cpu_cnt;
     715             : 
     716      151320 :   for( ulong cpu_rem=cpu_cnt; cpu_rem; cpu_rem-- ) {
     717      148992 :     ulong cpu_idx  = cpu_rem-1UL;
     718      148992 :     ulong numa_idx = fd_numa_node_idx( cpu_idx );
     719      148992 :     if( FD_UNLIKELY( numa_idx>=FD_SHMEM_NUMA_MAX) )
     720           0 :       FD_LOG_ERR(( "fd_shmem: unexpected numa idx (%lu) for cpu idx %lu", numa_idx, cpu_idx ));
     721      148992 :     fd_shmem_private_numa_idx[ cpu_idx  ] = (ushort)numa_idx;
     722      148992 :     fd_shmem_private_cpu_idx [ numa_idx ] = (ushort)cpu_idx;
     723      148992 :   }
     724             : 
     725             :   /* Determine the shared memory domain for this thread group */
     726             : 
     727        2328 :   char const * shmem_base = fd_env_strip_cmdline_cstr( pargc, pargv, "--shmem-path", "FD_SHMEM_PATH", "/mnt/.fd" );
     728             : 
     729        2328 :   ulong len = strlen( shmem_base );
     730        2328 :   while( (len>1UL) && (shmem_base[len-1UL]=='/') ) len--; /* lop off any trailing slashes */
     731        2328 :   if( FD_UNLIKELY( !len ) ) FD_LOG_ERR(( "Too short --shmem-base" ));
     732        2328 :   if( FD_UNLIKELY( len>=FD_SHMEM_PRIVATE_BASE_MAX ) ) FD_LOG_ERR(( "Too long --shmem-base" ));
     733        2328 :   fd_memcpy( fd_shmem_private_base, shmem_base, len );
     734        2328 :   fd_shmem_private_base[len] = '\0';
     735        2328 :   fd_shmem_private_base_len = (ulong)len;
     736             : 
     737             :   /* At this point, shared memory is online */
     738             : 
     739        2328 :   FD_LOG_INFO(( "fd_shmem: --shmem-path %s", fd_shmem_private_base ));
     740        2328 :   FD_LOG_INFO(( "fd_shmem: boot success" ));
     741        2328 : }
     742             : 
     743             : void
     744        1212 : fd_shmem_private_halt( void ) {
     745        1212 :   FD_LOG_INFO(( "fd_shmem: halting" ));
     746             : 
     747             :   /* At this point, shared memory is offline */
     748             : 
     749        1212 :   fd_shmem_private_numa_cnt = 0;
     750        1212 :   fd_shmem_private_cpu_cnt  = 0;
     751        1212 :   fd_memset( fd_shmem_private_numa_idx, 0, FD_SHMEM_CPU_MAX );
     752             : 
     753        1212 :   fd_shmem_private_base[0] = '\0';
     754        1212 :   fd_shmem_private_base_len = 0UL;
     755             : 
     756        1212 : # if FD_HAS_THREADS
     757        1212 :   if( FD_UNLIKELY( pthread_mutex_destroy( fd_shmem_private_lock ) ) )
     758           0 :     FD_LOG_WARNING(( "fd_shmem: pthread_mutex_destroy failed; attempting to continue" ));
     759        1212 : # endif /* FD_HAS_THREADS */
     760             : 
     761        1212 :   FD_LOG_INFO(( "fd_shmem: halt success" ));
     762        1212 : }
     763             : 
     764             : #else /* unhosted */
     765             : 
     766             : void
     767             : fd_shmem_private_boot( int *    pargc,
     768             :                        char *** pargv ) {
     769             :   FD_LOG_INFO(( "fd_shmem: booting" ));
     770             : 
     771             :   /* Strip the command line even though ignored to make environment
     772             :      parsing identical to downstream regardless of platform. */
     773             : 
     774             :   (void)fd_env_strip_cmdline_cstr( pargc, pargv, "--shmem-path", "FD_SHMEM_PATH", "/mnt/.fd" );
     775             : 
     776             :   FD_LOG_INFO(( "fd_shmem: --shmem-path (ignored)" ));
     777             :   FD_LOG_INFO(( "fd_shmem: boot success" ));
     778             : }
     779             : 
     780             : void
     781             : fd_shmem_private_halt( void ) {
     782             :   FD_LOG_INFO(( "fd_shmem: halting" ));
     783             :   FD_LOG_INFO(( "fd_shmem: halt success" ));
     784             : }
     785             : 
     786             : #endif

Generated by: LCOV version 1.14