LCOV - code coverage report
Current view: top level - disco/topo - fd_topo.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 63 359 17.5 %
Date: 2025-10-22 04:33:54 Functions: 5 22 22.7 %

          Line data    Source code
       1             : #include "fd_topo.h"
       2             : 
       3             : #include "../metrics/fd_metrics.h"
       4             : #include "../../util/pod/fd_pod_format.h"
       5             : #include "../../util/wksp/fd_wksp_private.h"
       6             : #include "../../util/shmem/fd_shmem_private.h"
       7             : 
       8             : #include <stdio.h>
       9             : #include <errno.h>
      10             : #include <unistd.h>
      11             : #include <sys/stat.h>
      12             : 
      13             : void *
      14             : fd_topo_obj_laddr( fd_topo_t const * topo,
      15        1800 :                    ulong             obj_id ) {
      16        1800 :   fd_topo_obj_t const * obj = &topo->objs[ obj_id ];
      17        1800 :   if( FD_UNLIKELY( obj_id==ULONG_MAX ) ) FD_LOG_CRIT(( "invalid obj_id ULONG_MAX" ));
      18        1800 :   if( FD_UNLIKELY( obj_id>=FD_TOPO_MAX_OBJS ) ) FD_LOG_CRIT(( "invalid obj_id %lu", obj_id ));
      19        1800 :   FD_TEST( obj->id == obj_id );
      20        1800 :   FD_TEST( obj->offset );
      21        1800 :   return (void *)((ulong)topo->workspaces[ obj->wksp_id ].wksp + obj->offset);
      22        1800 : }
      23             : 
      24             : void
      25             : fd_topo_join_workspace( fd_topo_t *      topo,
      26             :                         fd_topo_wksp_t * wksp,
      27           0 :                         int              mode ) {
      28           0 :   char name[ PATH_MAX ];
      29           0 :   FD_TEST( fd_cstr_printf_check( name, PATH_MAX, NULL, "%s_%s.wksp", topo->app_name, wksp->name ) );
      30             : 
      31           0 :   wksp->wksp = fd_wksp_join( fd_shmem_join( name, mode, NULL, NULL, NULL, wksp->is_locked ) );
      32           0 :   if( FD_UNLIKELY( !wksp->wksp ) ) FD_LOG_ERR(( "fd_wksp_join failed" ));
      33           0 : }
      34             : 
      35             : FD_FN_PURE static int
      36         336 : tile_needs_wksp( fd_topo_t const * topo, fd_topo_tile_t const * tile, ulong wksp_id ) {
      37         336 :   int mode = -1;
      38       11184 :   for( ulong i=0UL; i<tile->uses_obj_cnt; i++ ) {
      39       10848 :     if( FD_UNLIKELY( topo->objs[ tile->uses_obj_id[ i ] ].wksp_id==wksp_id ) ) {
      40         192 :       mode = fd_int_max( mode, tile->uses_obj_mode[ i ] );
      41         192 :     }
      42       10848 :   }
      43         336 :   return mode;
      44         336 : }
      45             : 
      46             : void
      47             : fd_topo_join_tile_workspaces( fd_topo_t *      topo,
      48           0 :                               fd_topo_tile_t * tile ) {
      49           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
      50           0 :     int needs_wksp = tile_needs_wksp( topo, tile, i );
      51           0 :     if( FD_LIKELY( -1!=needs_wksp ) ) {
      52           0 :       fd_topo_join_workspace( topo, &topo->workspaces[ i ], needs_wksp );
      53           0 :     }
      54           0 :   }
      55           0 : }
      56             : 
      57             : void
      58             : fd_topo_join_workspaces( fd_topo_t * topo,
      59           0 :                          int         mode ) {
      60           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
      61           0 :     fd_topo_join_workspace( topo, &topo->workspaces[ i ], mode );
      62           0 :   }
      63           0 : }
      64             : 
      65             : void
      66             : fd_topo_leave_workspace( fd_topo_t *      topo FD_PARAM_UNUSED,
      67           0 :                          fd_topo_wksp_t * wksp ) {
      68           0 :   if( FD_LIKELY( wksp->wksp ) ) {
      69           0 :     if( FD_UNLIKELY( fd_wksp_detach( wksp->wksp ) ) ) FD_LOG_ERR(( "fd_wksp_detach failed" ));
      70           0 :     wksp->wksp            = NULL;
      71           0 :     wksp->known_footprint = 0UL;
      72           0 :     wksp->total_footprint = 0UL;
      73           0 :   }
      74           0 : }
      75             : 
      76             : void
      77           0 : fd_topo_leave_workspaces( fd_topo_t * topo ) {
      78           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
      79           0 :     fd_topo_leave_workspace( topo, &topo->workspaces[ i ] );
      80           0 :   }
      81           0 : }
      82             : 
      83             : extern char fd_shmem_private_base[ FD_SHMEM_PRIVATE_BASE_MAX ];
      84             : 
      85             : int
      86             : fd_topo_create_workspace( fd_topo_t *      topo,
      87             :                           fd_topo_wksp_t * wksp,
      88           0 :                           int              update_existing ) {
      89           0 :   char name[ PATH_MAX ];
      90           0 :   FD_TEST( fd_cstr_printf_check( name, PATH_MAX, NULL, "%s_%s.wksp", topo->app_name, wksp->name ) );
      91             : 
      92           0 :   ulong sub_page_cnt[ 1 ] = { wksp->page_cnt };
      93           0 :   ulong sub_cpu_idx [ 1 ] = { fd_shmem_cpu_idx( wksp->numa_idx ) };
      94             : 
      95           0 :   int err;
      96           0 :   if( FD_UNLIKELY( !wksp->is_locked ) ) {
      97           0 :     err = fd_shmem_create_multi_unlocked( name, wksp->page_sz, wksp->page_cnt, S_IRUSR | S_IWUSR ); /* logs details */
      98           0 :   } else if( FD_UNLIKELY( update_existing ) ) {
      99           0 :     err = fd_shmem_update_multi( name, wksp->page_sz, 1, sub_page_cnt, sub_cpu_idx, S_IRUSR | S_IWUSR ); /* logs details */
     100           0 :   } else {
     101           0 :     err = fd_shmem_create_multi( name, wksp->page_sz, 1, sub_page_cnt, sub_cpu_idx, S_IRUSR | S_IWUSR ); /* logs details */
     102           0 :   }
     103           0 :   if( FD_UNLIKELY( err && errno==ENOMEM ) ) return -1;
     104           0 :   else if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_shmem_create_multi failed" ));
     105             : 
     106           0 :   void * shmem = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, NULL, wksp->is_locked ); /* logs details */
     107             : 
     108           0 :   void * wkspmem = fd_wksp_new( shmem, name, 0U, wksp->part_max, wksp->total_footprint ); /* logs details */
     109           0 :   if( FD_UNLIKELY( !wkspmem ) ) FD_LOG_ERR(( "fd_wksp_new failed" ));
     110             : 
     111           0 :   fd_wksp_t * join = fd_wksp_join( wkspmem );
     112           0 :   if( FD_UNLIKELY( !join ) ) FD_LOG_ERR(( "fd_wksp_join failed" ));
     113             : 
     114             :   /* Footprint has been predetermined so that this alloc() call must
     115             :       succeed inside the data region.  The difference between total_footprint
     116             :       and known_footprint is given to "loose" data, that may be dynamically
     117             :       allocated out of the workspace at runtime. */
     118           0 :   if( FD_LIKELY( wksp->known_footprint ) ) {
     119           0 :     ulong offset = fd_wksp_alloc( join, fd_topo_workspace_align(), wksp->known_footprint, 1UL );
     120           0 :     if( FD_UNLIKELY( !offset ) ) FD_LOG_ERR(( "fd_wksp_alloc failed" ));
     121             : 
     122             :     /* gaddr_lo is the start of the workspace data region that can be
     123             :         given out in response to wksp alloc requests.  We rely on an
     124             :         implicit assumption everywhere that the bytes we are given by
     125             :         this single allocation will be at gaddr_lo, so that we can find
     126             :         them, so we verify this here for paranoia in case the workspace
     127             :         alloc implementation changes. */
     128           0 :     if( FD_UNLIKELY( fd_ulong_align_up( ((struct fd_wksp_private*)join)->gaddr_lo, fd_topo_workspace_align() ) != offset ) )
     129           0 :       FD_LOG_ERR(( "wksp gaddr_lo %lu != offset %lu", fd_ulong_align_up( ((struct fd_wksp_private*)join)->gaddr_lo, fd_topo_workspace_align() ), offset ));
     130           0 :   }
     131             : 
     132           0 :   fd_wksp_leave( join );
     133             : 
     134           0 :   if( FD_UNLIKELY( fd_shmem_leave( shmem, NULL, NULL ) ) ) /* logs details */
     135           0 :     FD_LOG_ERR(( "fd_shmem_leave failed" ));
     136             : 
     137           0 :   return 0;
     138           0 : }
     139             : 
     140             : void
     141             : fd_topo_wksp_new( fd_topo_t const *          topo,
     142             :                   fd_topo_wksp_t const *     wksp,
     143          57 :                   fd_topo_obj_callbacks_t ** callbacks ) {
     144       14754 :   for( ulong i=0UL; i<topo->obj_cnt; i++ ) {
     145       14697 :     fd_topo_obj_t const * obj = &topo->objs[ i ];
     146       14697 :     if( FD_LIKELY( obj->wksp_id!=wksp->id ) ) continue;
     147             : 
     148        2568 :     for( ulong j=0UL; callbacks[ j ]; j++ ) {
     149        2568 :       if( FD_LIKELY( strcmp( callbacks[ j ]->name, obj->name ) ) ) continue;
     150             : 
     151         834 :       long ts = -fd_log_wallclock();
     152         834 :       if( FD_LIKELY( callbacks[ j ]->new ) ) callbacks[ j ]->new( topo, obj );
     153         834 :       long elapsed = fd_log_wallclock() + ts;
     154         834 :       if( FD_UNLIKELY( elapsed>(1000L*1000L*100L ) ) ) FD_LOG_WARNING(( "fd_topo_wksp_new(%s) took %ld ms", obj->name, elapsed/(1000L*1000L) ));
     155         834 :       else if( FD_UNLIKELY( elapsed>(1000L*1000L*5L ) ) ) FD_LOG_INFO(( "fd_topo_wksp_new(%s) took %ld ms", obj->name, elapsed/(1000L*1000L) ));
     156         834 :       break;
     157        2568 :     }
     158         834 :   }
     159          57 : }
     160             : 
     161             : void
     162             : fd_topo_workspace_fill( fd_topo_t *      topo,
     163          57 :                         fd_topo_wksp_t * wksp ) {
     164        2874 :   for( ulong i=0UL; i<topo->link_cnt; i++ ) {
     165        2817 :     fd_topo_link_t * link = &topo->links[ i ];
     166             : 
     167        2817 :     if( FD_UNLIKELY( topo->objs[ link->mcache_obj_id ].wksp_id!=wksp->id ) ) continue;
     168          75 :     link->mcache = fd_mcache_join( fd_topo_obj_laddr( topo, link->mcache_obj_id ) );
     169          75 :     FD_TEST( link->mcache );
     170             : 
     171          75 :     if( link->mtu ) {
     172          72 :       if( FD_UNLIKELY( topo->objs[ link->dcache_obj_id ].wksp_id!=wksp->id ) ) continue;
     173          72 :       link->dcache = fd_dcache_join( fd_topo_obj_laddr( topo, link->dcache_obj_id ) );
     174          72 :       FD_TEST( link->dcache );
     175          72 :     }
     176          75 :   }
     177             : 
     178        1755 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     179        1698 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     180             : 
     181        1698 :     if( FD_LIKELY( topo->objs[ tile->metrics_obj_id ].wksp_id==wksp->id ) ) {
     182         177 :       tile->metrics = fd_metrics_join( fd_topo_obj_laddr( topo, tile->metrics_obj_id ) );
     183         177 :       FD_TEST( tile->metrics );
     184         177 :     }
     185             : 
     186        6411 :     for( ulong j=0UL; j<tile->in_cnt; j++ ) {
     187        4713 :       if( FD_UNLIKELY( topo->objs[ tile->in_link_fseq_obj_id[ j ] ].wksp_id!=wksp->id ) ) continue;
     188         489 :       tile->in_link_fseq[ j ] = fd_fseq_join( fd_topo_obj_laddr( topo, tile->in_link_fseq_obj_id[ j ] ) );
     189         489 :       FD_TEST( tile->in_link_fseq[ j ] );
     190         489 :     }
     191        1698 :   }
     192          57 : }
     193             : 
     194             : void
     195             : fd_topo_fill_tile( fd_topo_t *      topo,
     196           6 :                    fd_topo_tile_t * tile ) {
     197         342 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     198         336 :     if( FD_UNLIKELY( -1!=tile_needs_wksp( topo, tile, i ) ) )
     199          57 :       fd_topo_workspace_fill( topo, &topo->workspaces[ i ] );
     200         336 :   }
     201           6 : }
     202             : 
     203             : void
     204           0 : fd_topo_fill( fd_topo_t * topo ) {
     205           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     206           0 :     fd_topo_workspace_fill( topo, &topo->workspaces[ i ] );
     207           0 :   }
     208           0 : }
     209             : 
     210             : FD_FN_CONST static ulong
     211           0 : fd_topo_tile_extra_huge_pages( fd_topo_tile_t const * tile ) {
     212             :   /* Every tile maps an additional set of pages for the stack. */
     213           0 :   (void)tile;
     214           0 :   return (FD_TILE_PRIVATE_STACK_SZ/FD_SHMEM_HUGE_PAGE_SZ)+2UL;
     215           0 : }
     216             : 
     217             : FD_FN_PURE static ulong
     218           0 : fd_topo_tile_extra_normal_pages( fd_topo_tile_t const * tile ) {
     219           0 :   ulong key_pages = 0UL;
     220           0 :   if( FD_UNLIKELY( tile->keyswitch_obj_id ) ) {
     221             :     /* Certain tiles using fd_keyload_load need normal pages to hold
     222             :        key material. */
     223           0 :     key_pages = 5UL;
     224           0 :   }
     225             : 
     226             :   /* All tiles lock one normal page for the fd_log shared lock. */
     227           0 :   return key_pages+1UL;
     228           0 : }
     229             : 
     230             : FD_FN_PURE static ulong
     231             : fd_topo_mlock_max_tile1( fd_topo_t const *      topo,
     232           0 :                          fd_topo_tile_t const * tile ) {
     233           0 :   ulong tile_mem = 0UL;
     234             : 
     235           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     236           0 :     if( FD_UNLIKELY( !topo->workspaces[ i ].is_locked ) ) continue;
     237             : 
     238           0 :     if( FD_UNLIKELY( -1!=tile_needs_wksp( topo, tile, i ) ) )
     239           0 :       tile_mem += topo->workspaces[ i ].page_cnt * topo->workspaces[ i ].page_sz;
     240           0 :   }
     241             : 
     242           0 :   return tile_mem +
     243           0 :       fd_topo_tile_extra_huge_pages( tile ) * FD_SHMEM_HUGE_PAGE_SZ +
     244           0 :       fd_topo_tile_extra_normal_pages( tile ) * FD_SHMEM_NORMAL_PAGE_SZ;
     245           0 : }
     246             : 
     247             : FD_FN_PURE ulong
     248           0 : fd_topo_mlock_max_tile( fd_topo_t const * topo ) {
     249           0 :   ulong highest_tile_mem = 0UL;
     250           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     251           0 :     fd_topo_tile_t const * tile = &topo->tiles[ i ];
     252           0 :     highest_tile_mem = fd_ulong_max( highest_tile_mem, fd_topo_mlock_max_tile1( topo, tile ) );
     253           0 :   }
     254             : 
     255           0 :   return highest_tile_mem;
     256           0 : }
     257             : 
     258             : FD_FN_PURE ulong
     259             : fd_topo_gigantic_page_cnt( fd_topo_t const * topo,
     260           0 :                            ulong             numa_idx ) {
     261           0 :   ulong result = 0UL;
     262           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     263           0 :     fd_topo_wksp_t const * wksp = &topo->workspaces[ i ];
     264           0 :     if( FD_LIKELY( wksp->numa_idx!=numa_idx ) ) continue;
     265             : 
     266           0 :     if( FD_LIKELY( wksp->page_sz==FD_SHMEM_GIGANTIC_PAGE_SZ ) ) {
     267           0 :       result += wksp->page_cnt;
     268           0 :     }
     269           0 :   }
     270           0 :   return result;
     271           0 : }
     272             : 
     273             : FD_FN_PURE ulong
     274             : fd_topo_huge_page_cnt( fd_topo_t const * topo,
     275             :                        ulong             numa_idx,
     276           0 :                        int               include_anonymous ) {
     277           0 :   ulong result = 0UL;
     278           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     279           0 :     fd_topo_wksp_t const * wksp = &topo->workspaces[ i ];
     280           0 :     if( FD_LIKELY( wksp->numa_idx!=numa_idx ) ) continue;
     281             : 
     282           0 :     if( FD_LIKELY( wksp->page_sz==FD_SHMEM_HUGE_PAGE_SZ ) ) {
     283           0 :       result += wksp->page_cnt;
     284           0 :     }
     285           0 :   }
     286             : 
     287             :   /* The stack huge pages are also placed in the hugetlbfs. */
     288           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     289           0 :     result += fd_topo_tile_extra_huge_pages( &topo->tiles[ i ] );
     290           0 :   }
     291             : 
     292             :   /* No anonymous huge pages in use yet. */
     293           0 :   (void)include_anonymous;
     294             : 
     295           0 :   return result;
     296           0 : }
     297             : 
     298             : FD_FN_PURE ulong
     299           0 : fd_topo_normal_page_cnt( fd_topo_t * topo ) {
     300           0 :   ulong result = 0UL;
     301           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     302           0 :     result += fd_topo_tile_extra_normal_pages( &topo->tiles[ i ] );
     303           0 :   }
     304           0 :   return result;
     305           0 : }
     306             : 
     307             : FD_FN_PURE ulong
     308           0 : fd_topo_mlock( fd_topo_t const * topo ) {
     309           0 :   ulong result = 0UL;
     310           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     311           0 :     if( FD_UNLIKELY( !topo->workspaces[ i ].is_locked ) ) continue;
     312           0 :     result += topo->workspaces[ i ].page_cnt * topo->workspaces[ i ].page_sz;
     313           0 :   }
     314           0 :   return result;
     315           0 : }
     316             : 
     317             : static void
     318           0 : fd_topo_mem_sz_string( ulong sz, char out[static 24] ) {
     319           0 :   if( FD_LIKELY( sz >= FD_SHMEM_GIGANTIC_PAGE_SZ ) ) {
     320           0 :     FD_TEST( fd_cstr_printf_check( out, 24, NULL, "%lu GiB", sz / (1 << 30) ) );
     321           0 :   } else if( FD_LIKELY( sz >= 1048576 ) ) {
     322           0 :     FD_TEST( fd_cstr_printf_check( out, 24, NULL, "%lu MiB", sz / (1 << 20) ) );
     323           0 :   } else if( FD_LIKELY( sz >= 1024 ) ) {
     324           0 :     FD_TEST( fd_cstr_printf_check( out, 24, NULL, "%lu KiB", sz / (1 << 10) ) );
     325           0 :   } else {
     326           0 :     FD_TEST( fd_cstr_printf_check( out, 24, NULL, "%lu B", sz ) );
     327           0 :   }
     328           0 : }
     329             : 
     330             : void
     331             : fd_topo_print_log( int         stdout,
     332           0 :                    fd_topo_t * topo ) {
     333           0 :   char message[ 32UL*4096UL ] = {0}; /* Same as FD_LOG_BUF_SZ */
     334             : 
     335           0 :   char * cur = message;
     336           0 :   ulong remaining = sizeof(message) - 1; /* Leave one character at the end to ensure NUL terminated */
     337             : 
     338           0 : #define PRINT( ... ) do {                                                           \
     339           0 :     int n = snprintf( cur, remaining, __VA_ARGS__ );                                \
     340           0 :     if( FD_UNLIKELY( n < 0 ) ) FD_LOG_ERR(( "snprintf failed" ));                   \
     341           0 :     if( FD_UNLIKELY( (ulong)n >= remaining ) ) FD_LOG_ERR(( "snprintf overflow" )); \
     342           0 :     remaining -= (ulong)n;                                                          \
     343           0 :     cur += n;                                                                       \
     344           0 :   } while( 0 )
     345             : 
     346           0 :   PRINT( "\nSUMMARY\n" );
     347             : 
     348             :   /* The logic to compute number of stack pages is taken from
     349             :      fd_tile_thread.cxx, in function fd_topo_tile_stack_join, and this
     350             :      should match that. */
     351           0 :   ulong stack_pages = topo->tile_cnt * FD_SHMEM_HUGE_PAGE_SZ * ((FD_TILE_PRIVATE_STACK_SZ/FD_SHMEM_HUGE_PAGE_SZ)+2UL);
     352             : 
     353             :   /* The logic to map these private pages into memory is in utility.c,
     354             :      under fd_keyload_load, and the amount of pages should be kept in
     355             :      sync. */
     356           0 :   ulong private_key_pages = 5UL * FD_SHMEM_NORMAL_PAGE_SZ;
     357           0 :   ulong total_bytes = fd_topo_mlock( topo ) + stack_pages + private_key_pages;
     358             : 
     359           0 :   PRINT("  %23s: %lu\n", "Total Tiles", topo->tile_cnt );
     360           0 :   PRINT("  %23s: %lu bytes (%lu GiB + %lu MiB + %lu KiB)\n",
     361           0 :     "Total Memory Locked",
     362           0 :     total_bytes,
     363           0 :     total_bytes / (1 << 30),
     364           0 :     (total_bytes % (1 << 30)) / (1 << 20),
     365           0 :     (total_bytes % (1 << 20)) / (1 << 10) );
     366             : 
     367           0 :   ulong required_gigantic_pages = 0UL;
     368           0 :   ulong required_huge_pages = 0UL;
     369             : 
     370           0 :   ulong numa_node_cnt = fd_shmem_numa_cnt();
     371           0 :   for( ulong i=0UL; i<numa_node_cnt; i++ ) {
     372           0 :     required_gigantic_pages += fd_topo_gigantic_page_cnt( topo, i );
     373           0 :     required_huge_pages += fd_topo_huge_page_cnt( topo, i, 0 );
     374           0 :   }
     375           0 :   PRINT("  %23s: %lu\n", "Required Gigantic Pages", required_gigantic_pages );
     376           0 :   PRINT("  %23s: %lu\n", "Required Huge Pages", required_huge_pages );
     377           0 :   PRINT("  %23s: %lu\n", "Required Normal Pages", fd_topo_normal_page_cnt( topo ) );
     378           0 :   for( ulong i=0UL; i<numa_node_cnt; i++ ) {
     379           0 :     PRINT("  %23s (NUMA node %lu): %lu\n", "Required Gigantic Pages", i, fd_topo_gigantic_page_cnt( topo, i ) );
     380           0 :     PRINT("  %23s (NUMA node %lu): %lu\n", "Required Huge Pages", i, fd_topo_huge_page_cnt( topo, i, 0 ) );
     381           0 :   }
     382             : 
     383           0 :   if( FD_UNLIKELY( topo->agave_affinity_cnt>0UL ) ) {
     384           0 :     char agave_affinity[4096];
     385           0 :     ulong offset = 0UL;
     386           0 :     for ( ulong i = 0UL; i < topo->agave_affinity_cnt; i++ ) {
     387           0 :       ulong sz;
     388           0 :       if( FD_LIKELY( i != 0UL )) FD_TEST( fd_cstr_printf_check( agave_affinity+offset, 4096-offset, &sz, ", %lu", topo->agave_affinity_cpu_idx[ i ] ) );
     389           0 :       else                       FD_TEST( fd_cstr_printf_check( agave_affinity+offset, 4096-offset, &sz, "%lu", topo->agave_affinity_cpu_idx[ i ] ) );
     390           0 :       offset += sz;
     391           0 :     }
     392           0 :     PRINT( "  %23s: %s\n", "Agave Affinity", agave_affinity );
     393           0 :   }
     394             : 
     395           0 :   PRINT( "\nWORKSPACES\n");
     396           0 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     397           0 :     fd_topo_wksp_t * wksp = &topo->workspaces[ i ];
     398             : 
     399           0 :     char size[ 24 ];
     400           0 :     fd_topo_mem_sz_string( wksp->page_sz * wksp->page_cnt, size );
     401           0 :     PRINT( "  %2lu (%7s): %12s  page_cnt=%3lu  page_sz=%-8s  numa_idx=%-2lu  footprint=%10lu  loose=%10lu  is_locked=%d\n", i, size, wksp->name, wksp->page_cnt, fd_shmem_page_sz_to_cstr( wksp->page_sz ), wksp->numa_idx, wksp->known_footprint, wksp->total_footprint - wksp->known_footprint, wksp->is_locked );
     402           0 :   }
     403             : 
     404           0 :   PRINT( "\nOBJECTS\n" );
     405           0 :   for( ulong i=0UL; i<topo->obj_cnt; i++ ) {
     406           0 :     fd_topo_obj_t * obj = &topo->objs[ i ];
     407             : 
     408           0 :     char size[ 24 ];
     409           0 :     fd_topo_mem_sz_string( obj->footprint, size );
     410           0 :     PRINT( "  %3lu: %12s %12s  wksp_id=%-2lu  footprint=%7s  offset=%lu",
     411           0 :            i, topo->workspaces[ obj->wksp_id ].name, obj->name,
     412           0 :            obj->wksp_id, size, obj->offset );
     413           0 :     for( fd_pod_iter_t iter=fd_pod_iter_init( fd_pod_queryf_subpod( topo->props, "obj.%lu", obj->id ) );
     414           0 :          !fd_pod_iter_done( iter );
     415           0 :          iter=fd_pod_iter_next( iter ) ) {
     416           0 :       fd_pod_info_t info = fd_pod_iter_info( iter );
     417           0 :       if( !strncmp( info.key, "seed", info.key_sz ) ) continue;
     418           0 :       PRINT( "  %.*s", (int)info.key_sz, info.key );
     419           0 :       switch( info.val_type ) {
     420           0 :       case FD_POD_VAL_TYPE_CSTR:
     421           0 :         PRINT( "=%.*s", (int)info.val_sz, (char const *)info.val );
     422           0 :         break;
     423           0 :       case FD_POD_VAL_TYPE_ULONG: {
     424           0 :         ulong val; fd_ulong_svw_dec( info.val, &val );
     425           0 :         PRINT( "=%lu", val );
     426           0 :         break;
     427           0 :       }
     428           0 :       }
     429           0 :     }
     430           0 :     PRINT( "\n" );
     431           0 :   }
     432             : 
     433           0 :   PRINT( "\nLINKS\n" );
     434           0 :   for( ulong i=0UL; i<topo->link_cnt; i++ ) {
     435           0 :     fd_topo_link_t * link = &topo->links[ i ];
     436             : 
     437           0 :     char size[ 24 ];
     438           0 :     fd_topo_mem_sz_string( fd_dcache_req_data_sz( link->mtu, link->depth, link->burst, 1 ), size );
     439           0 :     PRINT( "  %2lu (%7s): %12s  kind_id=%-2lu  wksp_id=%-2lu  depth=%-5lu  mtu=%-9lu  burst=%lu\n", i, size, link->name, link->kind_id, topo->objs[ link->dcache_obj_id ].wksp_id, link->depth, link->mtu, link->burst );
     440           0 :   }
     441             : 
     442           0 : #define PRINTIN( ... ) do {                                                            \
     443           0 :     int n = snprintf( cur_in, remaining_in, __VA_ARGS__ );                             \
     444           0 :     if( FD_UNLIKELY( n < 0 ) ) FD_LOG_ERR(( "snprintf failed" ));                      \
     445           0 :     if( FD_UNLIKELY( (ulong)n >= remaining_in ) ) FD_LOG_ERR(( "snprintf overflow" )); \
     446           0 :     remaining_in -= (ulong)n;                                                          \
     447           0 :     cur_in += n;                                                                       \
     448           0 :   } while( 0 )
     449             : 
     450           0 : #define PRINTOUT( ... ) do {                                                            \
     451           0 :     int n = snprintf( cur_out, remaining_out, __VA_ARGS__ );                            \
     452           0 :     if( FD_UNLIKELY( n < 0 ) ) FD_LOG_ERR(( "snprintf failed" ));                       \
     453           0 :     if( FD_UNLIKELY( (ulong)n >= remaining_out ) ) FD_LOG_ERR(( "snprintf overflow" )); \
     454           0 :     remaining_out -= (ulong)n;                                                          \
     455           0 :     cur_out += n;                                                                       \
     456           0 :   } while( 0 )
     457             : 
     458           0 :   PRINT( "\nTILES\n" );
     459           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     460           0 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     461             : 
     462           0 :     char in[ 256 ] = {0};
     463           0 :     char * cur_in = in;
     464           0 :     ulong remaining_in = sizeof( in ) - 1;
     465             : 
     466           0 :     for( ulong j=0UL; j<tile->in_cnt; j++ ) {
     467           0 :       if( FD_LIKELY( j != 0 ) ) PRINTIN( ", " );
     468           0 :       if( FD_LIKELY( tile->in_link_reliable[ j ] ) ) PRINTIN( "%2lu", tile->in_link_id[ j ] );
     469           0 :       else PRINTIN( "%2ld", (long)-tile->in_link_id[ j ] );
     470           0 :     }
     471             : 
     472           0 :     char out[ 256 ] = {0};
     473           0 :     char * cur_out = out;
     474           0 :     ulong remaining_out = sizeof( out ) - 1;
     475             : 
     476           0 :     for( ulong j=0UL; j<tile->out_cnt; j++ ) {
     477           0 :       if( FD_LIKELY( j != 0 ) ) PRINTOUT( ", " );
     478           0 :       PRINTOUT( "%2lu", tile->out_link_id[ j ] );
     479           0 :     }
     480             : 
     481             :     /* Determine tile's NUMA node either based on CPU or wksp affinity */
     482           0 :     ulong tile_numa = 0UL;
     483           0 :     if( tile->cpu_idx!=ULONG_MAX ) {
     484           0 :       tile_numa = fd_shmem_numa_idx( tile->cpu_idx );
     485           0 :     } else {
     486           0 :       tile_numa = topo->workspaces[ topo->objs[ tile->tile_obj_id ].wksp_id ].numa_idx;
     487           0 :     }
     488             : 
     489           0 :     char size[ 24 ];
     490           0 :     fd_topo_mem_sz_string( fd_topo_mlock_max_tile1( topo, tile ), size );
     491           0 :     PRINT( "  %2lu (%7s): %12s  kind_id=%-2lu  wksp_id=%-2lu  cpu_idx=", i, size, tile->name, tile->kind_id, topo->objs[ tile->tile_obj_id ].wksp_id );
     492           0 :     if( tile->cpu_idx!=ULONG_MAX ) {
     493           0 :       PRINT( "%3lu", tile->cpu_idx );
     494           0 :     } else {
     495           0 :       PRINT( "any" );
     496           0 :     }
     497             : 
     498           0 :     PRINT( "  numa_idx=%lu  in=[%s]  out=[%s]  objs=[", tile_numa, in, out );
     499           0 :     for( ulong j=0UL; j<tile->uses_obj_cnt; j++ ) {
     500           0 :       if( FD_LIKELY( j!=0 ) ) PRINT( " " );
     501           0 :       int is_rw = tile->uses_obj_mode[ j ] == FD_SHMEM_JOIN_MODE_READ_WRITE;
     502           0 :       PRINT( "%lu:%s", tile->uses_obj_id[ j ], is_rw?"rw":"ro" );
     503           0 :     }
     504           0 :     PRINT( "]" );
     505             : 
     506           0 :     if( FD_LIKELY( i != topo->tile_cnt-1 ) ) PRINT( "\n" );
     507           0 :   }
     508             : 
     509           0 :   if( FD_UNLIKELY( stdout ) ) FD_LOG_STDOUT(( "%s\n", message ));
     510           0 :   else                        FD_LOG_INFO(( "%s", message ));
     511           0 : }

Generated by: LCOV version 1.14