LCOV - code coverage report
Current view: top level - util/shmem - fd_shmem_admin.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 324 461 70.3 %
Date: 2026-11-12 04:25:03 Functions: 18 19 94.7 %

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

Generated by: LCOV version 1.14