LCOV - code coverage report
Current view: top level - disco/topo - fd_topob.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 320 338 94.7 %
Date: 2025-01-08 12:08:44 Functions: 11 11 100.0 %

          Line data    Source code
       1             : #include "fd_topob.h"
       2             : 
       3             : #include "fd_pod_format.h"
       4             : #include "../../util/shmem/fd_shmem_private.h"
       5             : 
       6             : fd_topo_t *
       7             : fd_topob_new( void * mem,
       8           3 :               char const * app_name ) {
       9           3 :   fd_topo_t * topo = (fd_topo_t *)mem;
      10             : 
      11           3 :   if( FD_UNLIKELY( !topo ) ) {
      12           0 :     FD_LOG_WARNING( ( "NULL topo" ) );
      13           0 :     return NULL;
      14           0 :   }
      15             : 
      16           3 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)topo, alignof(fd_topo_t) ) ) ) {
      17           0 :     FD_LOG_WARNING( ( "misaligned topo" ) );
      18           0 :     return NULL;
      19           0 :   }
      20             : 
      21           3 :   fd_memset( topo, 0, sizeof(fd_topo_t) );
      22             : 
      23           3 :   FD_TEST( fd_pod_new( topo->props, sizeof(topo->props) ) );
      24             : 
      25           3 :   if( FD_UNLIKELY( strlen( app_name )>=sizeof(topo->app_name) ) ) FD_LOG_ERR(( "app_name too long: %s", app_name ));
      26           3 :   strncpy( topo->app_name, app_name, sizeof(topo->app_name) );
      27             : 
      28           3 :   return topo;
      29           3 : }
      30             : 
      31             : void
      32             : fd_topob_wksp( fd_topo_t *  topo,
      33          99 :                char const * name ) {
      34          99 :   if( FD_UNLIKELY( !topo || !name || !strlen( name ) ) ) FD_LOG_ERR(( "NULL args" ));
      35          99 :   if( FD_UNLIKELY( strlen( name )>=sizeof(topo->workspaces[ topo->wksp_cnt ].name ) ) ) FD_LOG_ERR(( "wksp name too long: %s", name ));
      36          99 :   if( FD_UNLIKELY( topo->wksp_cnt>=FD_TOPO_MAX_WKSPS ) ) FD_LOG_ERR(( "too many workspaces" ));
      37             : 
      38          99 :   fd_topo_wksp_t * wksp = &topo->workspaces[ topo->wksp_cnt ];
      39          99 :   strncpy( wksp->name, name, sizeof(wksp->name) );
      40          99 :   wksp->id = topo->wksp_cnt;
      41          99 :   topo->wksp_cnt++;
      42          99 : }
      43             : 
      44             : fd_topo_obj_t *
      45             : fd_topob_obj( fd_topo_t *  topo,
      46             :               char const * obj_name,
      47         495 :               char const * wksp_name ) {
      48         495 :   if( FD_UNLIKELY( !topo || !obj_name || !wksp_name ) ) FD_LOG_ERR(( "NULL args" ));
      49         495 :   if( FD_UNLIKELY( strlen( obj_name )>=sizeof(topo->objs[ topo->obj_cnt ].name ) ) ) FD_LOG_ERR(( "obj name too long: %s", obj_name ));
      50         495 :   if( FD_UNLIKELY( topo->obj_cnt>=FD_TOPO_MAX_OBJS ) ) FD_LOG_ERR(( "too many objects" ));
      51             : 
      52         495 :   ulong wksp_id = fd_topo_find_wksp( topo, wksp_name );
      53         495 :   if( FD_UNLIKELY( wksp_id==ULONG_MAX ) ) FD_LOG_ERR(( "workspace not found: %s", wksp_name ));
      54             : 
      55         495 :   fd_topo_obj_t * obj = &topo->objs[ topo->obj_cnt ];
      56         495 :   strncpy( obj->name, obj_name, sizeof(obj->name) );
      57         495 :   obj->id      = topo->obj_cnt;
      58         495 :   obj->wksp_id = wksp_id;
      59         495 :   topo->obj_cnt++;
      60             : 
      61         495 :   return obj;
      62         495 : }
      63             : 
      64             : void
      65             : fd_topob_link( fd_topo_t *  topo,
      66             :                char const * link_name,
      67             :                char const * wksp_name,
      68             :                ulong        depth,
      69             :                ulong        mtu,
      70          99 :                ulong        burst ) {
      71          99 :   if( FD_UNLIKELY( !topo || !link_name || !wksp_name ) ) FD_LOG_ERR(( "NULL args" ));
      72          99 :   if( FD_UNLIKELY( strlen( link_name )>=sizeof(topo->links[ topo->link_cnt ].name ) ) ) FD_LOG_ERR(( "link name too long: %s", link_name ));
      73          99 :   if( FD_UNLIKELY( topo->link_cnt>=FD_TOPO_MAX_LINKS ) ) FD_LOG_ERR(( "too many links" ));
      74             : 
      75          99 :   ulong kind_id = 0UL;
      76        1683 :   for( ulong i=0UL; i<topo->link_cnt; i++ ) {
      77        1584 :     if( !strcmp( topo->links[ i ].name, link_name ) ) kind_id++;
      78        1584 :   }
      79             : 
      80          99 :   fd_topo_link_t * link = &topo->links[ topo->link_cnt ];
      81          99 :   strncpy( link->name, link_name, sizeof(link->name) );
      82          99 :   link->id       = topo->link_cnt;
      83          99 :   link->kind_id  = kind_id;
      84          99 :   link->depth    = depth;
      85          99 :   link->mtu      = mtu;
      86          99 :   link->burst    = burst;
      87             : 
      88          99 :   fd_topo_obj_t * obj = fd_topob_obj( topo, "mcache", wksp_name );
      89          99 :   link->mcache_obj_id = obj->id;
      90          99 :   FD_TEST( fd_pod_insertf_ulong( topo->props, depth, "obj.%lu.depth", obj->id ) );
      91             : 
      92          99 :   obj = fd_topob_obj( topo, "dcache", wksp_name );
      93          99 :   link->dcache_obj_id = obj->id;
      94          99 :   FD_TEST( fd_pod_insertf_ulong( topo->props, depth, "obj.%lu.depth", obj->id ) );
      95          99 :   FD_TEST( fd_pod_insertf_ulong( topo->props, burst, "obj.%lu.burst", obj->id ) );
      96          99 :   FD_TEST( fd_pod_insertf_ulong( topo->props, mtu, "obj.%lu.mtu", obj->id ) );
      97          99 :   topo->link_cnt++;
      98          99 : }
      99             : 
     100             : void
     101             : fd_topob_tile_uses( fd_topo_t *      topo,
     102             :                     fd_topo_tile_t * tile,
     103             :                     fd_topo_obj_t *  obj,
     104         798 :                     int              mode ) {
     105         798 :   (void)topo;
     106             : 
     107         798 :   if( FD_UNLIKELY( tile->uses_obj_cnt>=FD_TOPO_MAX_TILE_OBJS ) ) FD_LOG_ERR(( "tile `%s` uses too many objects", tile->name ));
     108             : 
     109         798 :   tile->uses_obj_id[ tile->uses_obj_cnt ] = obj->id;
     110         798 :   tile->uses_obj_mode[ tile->uses_obj_cnt ] = mode;
     111         798 :   tile->uses_obj_cnt++;
     112         798 : }
     113             : 
     114             : fd_topo_tile_t *
     115             : fd_topob_tile( fd_topo_t *    topo,
     116             :                char const *   tile_name,
     117             :                char const *   tile_wksp,
     118             :                char const *   metrics_wksp,
     119             :                ulong          cpu_idx,
     120          69 :                int            is_agave ) {
     121             : 
     122          69 :   if( FD_UNLIKELY( !topo || !tile_name || !tile_wksp || !metrics_wksp ) ) FD_LOG_ERR(( "NULL args" ));
     123          69 :   if( FD_UNLIKELY( strlen( tile_name )>=sizeof(topo->tiles[ topo->tile_cnt ].name ) ) ) FD_LOG_ERR(( "tile name too long: %s", tile_name ));
     124          69 :   if( FD_UNLIKELY( topo->tile_cnt>=FD_TOPO_MAX_TILES ) ) FD_LOG_ERR(( "too many tiles" ));
     125             : 
     126          69 :   ulong kind_id = 0UL;
     127         828 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     128         759 :     if( !strcmp( topo->tiles[ i ].name, tile_name ) ) kind_id++;
     129         759 :   }
     130             : 
     131          69 :   fd_topo_tile_t * tile = &topo->tiles[ topo->tile_cnt ];
     132          69 :   strncpy( tile->name, tile_name, sizeof(tile->name) );
     133          69 :   tile->id                  = topo->tile_cnt;
     134          69 :   tile->kind_id             = kind_id;
     135          69 :   tile->is_agave            = is_agave;
     136          69 :   tile->cpu_idx             = cpu_idx;
     137          69 :   tile->in_cnt              = 0UL;
     138          69 :   tile->out_cnt             = 0UL;
     139          69 :   tile->uses_obj_cnt        = 0UL;
     140             : 
     141          69 :   fd_topo_obj_t * tile_obj = fd_topob_obj( topo, "tile", tile_wksp );
     142          69 :   tile->tile_obj_id = tile_obj->id;
     143          69 :   fd_topob_tile_uses( topo, tile, tile_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     144             : 
     145          69 :   fd_topo_obj_t * obj = fd_topob_obj( topo, "metrics", metrics_wksp );
     146          69 :   tile->metrics_obj_id = obj->id;
     147          69 :   fd_topob_tile_uses( topo, tile, obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     148             : 
     149          69 :   topo->tile_cnt++;
     150          69 :   return tile;
     151          69 : }
     152             : 
     153             : void
     154             : fd_topob_tile_in( fd_topo_t *  topo,
     155             :                   char const * tile_name,
     156             :                   ulong        tile_kind_id,
     157             :                   char const * fseq_wksp,
     158             :                   char const * link_name,
     159             :                   ulong        link_kind_id,
     160             :                   int          reliable,
     161         144 :                   int          polled ) {
     162         144 :   if( FD_UNLIKELY( !topo || !tile_name || !fseq_wksp || !link_name ) ) FD_LOG_ERR(( "NULL args" ));
     163             : 
     164         144 :   ulong tile_id = fd_topo_find_tile( topo, tile_name, tile_kind_id );
     165         144 :   if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) FD_LOG_ERR(( "tile not found: %s:%lu", tile_name, tile_kind_id ));
     166         144 :   fd_topo_tile_t * tile = &topo->tiles[ tile_id ];
     167             : 
     168         144 :   ulong link_id = fd_topo_find_link( topo, link_name, link_kind_id );
     169         144 :   if( FD_UNLIKELY( link_id==ULONG_MAX ) ) FD_LOG_ERR(( "link not found: %s:%lu", link_name, link_kind_id ));
     170         144 :   fd_topo_link_t * link = &topo->links[ link_id ];
     171             : 
     172         144 :   if( FD_UNLIKELY( tile->in_cnt>=FD_TOPO_MAX_TILE_IN_LINKS ) ) FD_LOG_ERR(( "too many in links: %s:%lu", tile_name, tile_kind_id ) );
     173         144 :   tile->in_link_id[ tile->in_cnt ] = link->id;
     174         144 :   tile->in_link_reliable[ tile->in_cnt ] = reliable;
     175         144 :   tile->in_link_poll[ tile->in_cnt ] = polled;
     176         144 :   fd_topo_obj_t * obj = fd_topob_obj( topo, "fseq", fseq_wksp );
     177         144 :   fd_topob_tile_uses( topo, tile, obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     178         144 :   tile->in_link_fseq_obj_id[ tile->in_cnt ] = obj->id;
     179         144 :   tile->in_cnt++;
     180             : 
     181         144 :   fd_topob_tile_uses( topo, tile, &topo->objs[ link->mcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
     182         144 :   if( FD_LIKELY( link->mtu ) ) {
     183         144 :     fd_topob_tile_uses( topo, tile, &topo->objs[ link->dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
     184         144 :   }
     185         144 : }
     186             : 
     187             : void
     188             : fd_topob_tile_out( fd_topo_t *  topo,
     189             :                    char const * tile_name,
     190             :                    ulong        tile_kind_id,
     191             :                    char const * link_name,
     192          99 :                    ulong        link_kind_id ) {
     193          99 :   ulong tile_id = fd_topo_find_tile( topo, tile_name, tile_kind_id );
     194          99 :   if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) FD_LOG_ERR(( "tile not found: %s:%lu", tile_name, tile_kind_id ));
     195          99 :   fd_topo_tile_t * tile = &topo->tiles[ tile_id ];
     196             : 
     197          99 :   ulong link_id = fd_topo_find_link( topo, link_name, link_kind_id );
     198          99 :   if( FD_UNLIKELY( link_id==ULONG_MAX ) ) FD_LOG_ERR(( "link not found: %s:%lu", link_name, link_kind_id ));
     199          99 :   fd_topo_link_t * link = &topo->links[ link_id ];
     200             : 
     201          99 :   if( FD_UNLIKELY( tile->out_cnt>=FD_TOPO_MAX_TILE_OUT_LINKS ) ) FD_LOG_ERR(( "too many out links: %s", tile_name ));
     202          99 :   tile->out_link_id[ tile->out_cnt ] = link->id;
     203          99 :   tile->out_cnt++;
     204             : 
     205          99 :   fd_topob_tile_uses( topo, tile, &topo->objs[ link->mcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
     206          99 :   if( FD_LIKELY( link->mtu ) ) {
     207          99 :     fd_topob_tile_uses( topo, tile, &topo->objs[ link->dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
     208          99 :   }
     209          99 : }
     210             : 
     211             : static void
     212           3 : validate( fd_topo_t const * topo ) {
     213             :   /* Objects have valid wksp_ids */
     214         498 :   for( ulong i=0UL; i<topo->obj_cnt; i++ ) {
     215         495 :     if( FD_UNLIKELY( topo->objs[ i ].wksp_id>=topo->wksp_cnt ) )
     216           0 :       FD_LOG_ERR(( "invalid workspace id %lu", topo->objs[ i ].wksp_id ));
     217         495 :   }
     218             : 
     219             :   /* Tile ins are valid */
     220          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     221         213 :     for( ulong j=0UL; j<topo->tiles[ i ].in_cnt; j++ ) {
     222         144 :       if( FD_UNLIKELY( topo->tiles[ i ].in_link_id[ j ]>=topo->link_cnt ) )
     223           0 :         FD_LOG_ERR(( "tile %lu (%s) has invalid in link %lu", i, topo->tiles[ i ].name, topo->tiles[ i ].in_link_id[ j ] ));
     224         144 :     }
     225          69 :   }
     226             : 
     227             :   /* Tile does not have duplicated ins */
     228          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     229         213 :     for( ulong j=0UL; j<topo->tiles[ i ].in_cnt; j++ ) {
     230         756 :       for( ulong k=0UL; k<topo->tiles[ i ].in_cnt; k++ ) {
     231         612 :         if( FD_UNLIKELY( j==k ) ) continue;
     232         468 :         if( FD_UNLIKELY( topo->tiles[ i ].in_link_id[ j ] == topo->tiles[ i ].in_link_id[ k ] ) )
     233           0 :           FD_LOG_ERR(( "tile %lu (%s) has duplicated in link %lu (%s)", i, topo->tiles[ i ].name,
     234         468 :               topo->tiles[ i ].in_link_id[ j ], topo->links[ topo->tiles[ i ].in_link_id[ j ] ].name ));
     235         468 :       }
     236         144 :     }
     237          69 :   }
     238             : 
     239             :   /* Tile does not have duplicated outs */
     240          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     241         168 :     for( ulong j=0UL; j<topo->tiles[ i ].out_cnt; j++ ) {
     242         558 :       for( ulong k=0UL; k<topo->tiles[ i ].out_cnt; k++ ) {
     243         459 :         if( FD_UNLIKELY( j==k ) ) continue;
     244         360 :         if( FD_UNLIKELY( topo->tiles[ i ].out_link_id[ j ] == topo->tiles[ i ].out_link_id[ k ] ) )
     245           0 :           FD_LOG_ERR(( "tile %lu (%s) has duplicated out link %lu (%s)", i, topo->tiles[ i ].name,
     246         360 :               topo->tiles[ i ].out_link_id[ j ], topo->links[ topo->tiles[ i ].out_link_id[ j ] ].name ));
     247         360 :       }
     248          99 :     }
     249          69 :   }
     250             : 
     251             :   /* Tile outs are different than ins */
     252          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     253         168 :     for( ulong j=0UL; j<topo->tiles[ i ].out_cnt; j++ ) {
     254         456 :       for( ulong k=0UL; k<topo->tiles[ i ].in_cnt; k++ ) {
     255         357 :         char const * link_name = topo->links[ topo->tiles[ i ].out_link_id[ j ] ].name;
     256             :         /* PoH tile "publishes" this on behalf of Agave, so it's not
     257             :            a real circular link. */
     258         357 :         if( FD_UNLIKELY( !strcmp( link_name, "stake_out" ) ||
     259         357 :                          !strcmp( link_name, "crds_shred" ) ) ) continue;
     260             : 
     261         321 :         if( FD_UNLIKELY( topo->tiles[ i ].out_link_id[ j ] == topo->tiles[ i ].in_link_id[ k ] ) )
     262           0 :           FD_LOG_ERR(( "tile %lu has out link %lu same as in", i, topo->tiles[ i ].out_link_id[ j ] ));
     263         321 :       }
     264          99 :     }
     265          69 :   }
     266             : 
     267             :   /* Non polling tile ins are also not reliable */
     268          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     269         213 :     for( ulong j=0UL; j<topo->tiles[ i ].in_cnt; j++ ) {
     270         144 :       if( FD_UNLIKELY( !topo->tiles[ i ].in_link_poll[ j ] && topo->tiles[ i ].in_link_reliable[ j ] ) )
     271           0 :         FD_LOG_ERR(( "tile %lu has in link %lu which is not polled but reliable", i, topo->tiles[ i ].in_link_id[ j ] ));
     272         144 :     }
     273          69 :   }
     274             : 
     275             :   /* Tile outs are valid */
     276          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     277         168 :     for( ulong j=0UL; j<topo->tiles[ i ].out_cnt; j++ ) {
     278          99 :       if( FD_UNLIKELY( topo->tiles[ i ].out_link_id[ j ] >= topo->link_cnt ) )
     279           0 :         FD_LOG_ERR(( "tile %lu has invalid out link %lu", i, topo->tiles[ i ].out_link_id[ j ] ));
     280          99 :     }
     281          69 :   }
     282             : 
     283             :   /* Workspace names are unique */
     284         102 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     285        3366 :     for( ulong j=0UL; j<topo->wksp_cnt; j++ ) {
     286        3267 :       if( FD_UNLIKELY( i==j ) ) continue;
     287        3168 :       if( FD_UNLIKELY( !strcmp( topo->workspaces[ i ].name,  topo->workspaces[ j ].name ) ) )
     288           0 :         FD_LOG_ERR(( "duplicate workspace name %s", topo->workspaces[ i ].name ));
     289        3168 :     }
     290          99 :   }
     291             : 
     292             :   /* Each workspace is identified correctly */
     293         102 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     294          99 :     if( FD_UNLIKELY( topo->workspaces[ i ].id != i ) )
     295           0 :       FD_LOG_ERR(( "workspace %lu has id %lu", i, topo->workspaces[ i ].id ));
     296          99 :   }
     297             : 
     298             :   /* Each link has exactly one producer */
     299         102 :   for( ulong i=0UL; i<topo->link_cnt; i++ ) {
     300          99 :     ulong producer_cnt = 0;
     301        2376 :     for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
     302        5544 :       for( ulong k=0UL; k<topo->tiles[ j ].out_cnt; k++ ) {
     303        3267 :         if( topo->tiles[ j ].out_link_id[ k ]==i ) producer_cnt++;
     304        3267 :       }
     305        2277 :     }
     306          99 :     if( FD_UNLIKELY( producer_cnt!=1UL ) )
     307           0 :       FD_LOG_ERR(( "link %lu (%s:%lu) has %lu producers", i, topo->links[ i ].name, topo->links[ i ].kind_id, producer_cnt ));
     308          99 :   }
     309             : 
     310             :   /* Each link has at least one consumer */
     311         102 :   for( ulong i=0UL; i<topo->link_cnt; i++ ) {
     312          99 :     ulong cnt = fd_topo_link_consumer_cnt( topo, &topo->links[ i ] );
     313          99 :     if( FD_UNLIKELY( cnt < 1 ) )
     314           0 :       FD_LOG_ERR(( "link %lu (%s:%lu) has %lu consumers", i, topo->links[ i ].name, topo->links[ i ].kind_id, cnt ));
     315          99 :   }
     316           3 : }
     317             : 
     318             : void
     319           3 : fd_topob_auto_layout( fd_topo_t * topo ) {
     320             :   /* Incredibly simple automatic layout system for now ... just assign
     321             :      tiles to CPU cores in NUMA sequential order, except for a few tiles
     322             :      which should be floating. */
     323             : 
     324           3 :   char const * FLOATING[] = {
     325           3 :     "metric",
     326           3 :     "cswtch",
     327           3 :     "bencho",
     328           3 :     "bhole",  /* FIREDANCER only */
     329           3 :   };
     330             : 
     331           3 :   char const * ORDERED[] = {
     332           3 :     "benchg",
     333           3 :     "benchs",
     334           3 :     "net",
     335           3 :     "quic",
     336           3 :     "verify",
     337           3 :     "dedup",
     338           3 :     "resolv",
     339           3 :     "pack",
     340           3 :     "bank",
     341           3 :     "poh",
     342             : #ifdef FD_HAS_NO_AGAVE
     343             :     "pohi",   /* FIREDANCER only */
     344             : #endif
     345           3 :     "shred",
     346           3 :     "store",
     347             : #ifdef FD_HAS_NO_AGAVE
     348             :     "storei", /* FIREDANCER only */
     349             : #endif
     350           3 :     "sign",
     351           3 :     "plugin",
     352           3 :     "gui",
     353             : #ifdef FD_HAS_NO_AGAVE
     354             :     "gossip", /* FIREDANCER only */
     355             :     "repair", /* FIREDANCER only */
     356             :     "replay", /* FIREDANCER only */
     357             :     "rtpool", /* FIREDANCER only */
     358             :     "sender", /* FIREDANCER only */
     359             :     "eqvoc",  /* FIREDANCER only */
     360             :     "rpcsrv", /* FIREDANCER only */
     361             :     "snaps",  /* FIREDANCER only */
     362             :     "stpool", /* FIREDANCER only */
     363             : #endif
     364           3 :   };
     365             : 
     366          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     367          69 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     368          69 :     tile->cpu_idx = ULONG_MAX;
     369          69 :   }
     370             : 
     371           3 :   ulong cpu_ordering[ FD_TILE_MAX ] = { 0UL };
     372           3 :   ulong num_cpus = fd_numa_cpu_cnt();
     373             : 
     374           3 :   ulong next_cpu_idx = 0UL;
     375           3 :   ulong num_numa_nodes = fd_numa_node_cnt();
     376           6 :   for( ulong i=0UL; i<num_numa_nodes; i++ ) {
     377         195 :     for( ulong j=0UL; j<num_cpus; j++ ) {
     378         192 :       ulong numa_node = fd_numa_node_idx( j );
     379         192 :       if( FD_UNLIKELY( numa_node!=i ) ) continue;
     380         192 :       FD_TEST( next_cpu_idx<FD_TILE_MAX );
     381         192 :       cpu_ordering[ next_cpu_idx++ ] = j;
     382         192 :     }
     383           3 :   }
     384             : 
     385           3 :   FD_TEST( next_cpu_idx==num_cpus );
     386             : 
     387           3 :   ulong cpu_idx = 0UL;
     388          48 :   for( ulong i=0UL; i<sizeof(ORDERED)/sizeof(ORDERED[0]); i++ ) {
     389        1080 :     for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
     390        1035 :       fd_topo_tile_t * tile = &topo->tiles[ j ];
     391        1035 :       if( !strcmp( tile->name, ORDERED[ i ] ) ) {
     392          63 :         if( FD_UNLIKELY( cpu_idx>=num_cpus ) ) {
     393           0 :           FD_LOG_ERR(( "auto layout cannot set affinity for tile `%s:%lu` because all the CPUs are already assigned", tile->name, tile->kind_id ));
     394          63 :         } else {
     395          63 :           tile->cpu_idx = cpu_ordering[ cpu_idx++ ];
     396          63 :         }
     397          63 :       }
     398        1035 :     }
     399          45 :   }
     400             : 
     401             :   /* Make sure all the tiles we haven't set are supposed to be floating. */
     402          72 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     403          69 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     404          69 :     if( tile->cpu_idx!=ULONG_MAX ) continue;
     405             : 
     406           6 :     int found = 0;
     407           9 :     for( ulong j=0UL; j<sizeof(FLOATING)/sizeof(FLOATING[0]); j++ ) {
     408           9 :       if( !strcmp( tile->name, FLOATING[ j ] ) ) {
     409           6 :         found = 1;
     410           6 :         break;
     411           6 :       }
     412           9 :     }
     413             : 
     414           6 :     if( FD_UNLIKELY( !found ) ) FD_LOG_WARNING(( "auto layout cannot affine tile `%s:%lu` because it is unknown. Leaving it floating", tile->name, tile->kind_id ));
     415           6 :   }
     416             : 
     417         132 :   for( ulong i=cpu_idx; i<num_cpus; i++ ) {
     418         129 :     if( FD_LIKELY( topo->agave_affinity_cnt<sizeof(topo->agave_affinity_cpu_idx)/sizeof(topo->agave_affinity_cpu_idx[0]) ) ) {
     419         129 :       topo->agave_affinity_cpu_idx[ topo->agave_affinity_cnt++ ] = cpu_ordering[ i ];
     420         129 :     }
     421         129 :   }
     422           3 : }
     423             : 
     424             : void
     425             : fd_topob_finish( fd_topo_t * topo,
     426             :                  ulong (* align    )( fd_topo_t const * topo, fd_topo_obj_t const * obj ),
     427             :                  ulong (* footprint)( fd_topo_t const * topo, fd_topo_obj_t const * obj ),
     428           3 :                  ulong (* loose    )( fd_topo_t const * topo, fd_topo_obj_t const * obj) ) {
     429          72 :   for( ulong z=0UL; z<topo->tile_cnt; z++ ) {
     430          69 :     fd_topo_tile_t * tile = &topo->tiles[ z ];
     431             : 
     432          69 :     ulong in_cnt = 0UL;
     433         213 :     for( ulong i=0UL; i<tile->in_cnt; i++ ) {
     434         144 :       if( FD_UNLIKELY( !tile->in_link_poll[ i ] ) ) continue;
     435         141 :       in_cnt++;
     436         141 :     }
     437             : 
     438          69 :     ulong cons_cnt = 0UL;
     439        1656 :     for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     440        1587 :       fd_topo_tile_t * consumer_tile = &topo->tiles[ i ];
     441        4899 :       for( ulong j=0UL; j<consumer_tile->in_cnt; j++ ) {
     442        8064 :         for( ulong k=0UL; k<tile->out_cnt; k++ ) {
     443        4752 :           if( FD_UNLIKELY( consumer_tile->in_link_id[ j ]==tile->out_link_id[ k ] && consumer_tile->in_link_reliable[ j ] ) ) {
     444          93 :             cons_cnt++;
     445          93 :           }
     446        4752 :         }
     447        3312 :       }
     448        1587 :     }
     449             : 
     450          69 :     FD_TEST( !fd_pod_replacef_ulong( topo->props, in_cnt, "obj.%lu.in_cnt", tile->metrics_obj_id ) );
     451          69 :     FD_TEST( !fd_pod_replacef_ulong( topo->props, cons_cnt, "obj.%lu.cons_cnt", tile->metrics_obj_id ) );
     452          69 :   }
     453             : 
     454         102 :   for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
     455          99 :     fd_topo_wksp_t * wksp = &topo->workspaces[ i ];
     456             : 
     457          99 :     ulong loose_sz = 0UL;
     458       16434 :     for( ulong j=0UL; j<topo->obj_cnt; j++ ) {
     459       16335 :       fd_topo_obj_t * obj = &topo->objs[ j ];
     460       16335 :       if( FD_UNLIKELY( obj->wksp_id!=wksp->id ) ) continue;
     461         495 :       loose_sz += loose( topo, obj );
     462         495 :     }
     463             : 
     464          99 :     ulong part_max = 3UL + (loose_sz / (64UL << 10)); /* 3 for initial alignment + actual alloc + residual padding */
     465          99 :     ulong offset = fd_ulong_align_up( fd_wksp_private_data_off( part_max ), fd_topo_workspace_align() );
     466             : 
     467       16434 :     for( ulong j=0UL; j<topo->obj_cnt; j++ ) {
     468       16335 :       fd_topo_obj_t * obj = &topo->objs[ j ];
     469       16335 :       if( FD_UNLIKELY( obj->wksp_id!=wksp->id ) ) continue;
     470             : 
     471         495 :       offset = fd_ulong_align_up( offset, align( topo, obj ) );
     472         495 :       obj->offset = offset;
     473         495 :       obj->footprint = footprint( topo, obj );
     474         495 :       offset += obj->footprint;
     475         495 :     }
     476             : 
     477          99 :     ulong footprint = fd_ulong_align_up( offset, fd_topo_workspace_align() );
     478             : 
     479             :     /* Compute footprint for a workspace that can store our footprint,
     480             :        with an extra align of padding incase gaddr_lo is not aligned. */
     481          99 :     ulong total_wksp_footprint = fd_wksp_footprint( part_max, footprint + fd_topo_workspace_align() + loose_sz );
     482             : 
     483          99 :     ulong page_sz = FD_SHMEM_GIGANTIC_PAGE_SZ;
     484          99 :     if( FD_UNLIKELY( total_wksp_footprint < 4 * FD_SHMEM_HUGE_PAGE_SZ ) ) page_sz = FD_SHMEM_HUGE_PAGE_SZ;
     485             : 
     486          99 :     ulong wksp_aligned_footprint = fd_ulong_align_up( total_wksp_footprint, page_sz );
     487             : 
     488             :     /* Give any leftover space in the underlying shared memory to the
     489             :        data region of the workspace, since we might as well use it. */
     490          99 :     wksp->part_max = part_max;
     491          99 :     wksp->known_footprint = footprint;
     492          99 :     wksp->total_footprint = wksp_aligned_footprint - fd_ulong_align_up( fd_wksp_private_data_off( part_max ), fd_topo_workspace_align() );
     493          99 :     wksp->page_sz = page_sz;
     494          99 :     wksp->page_cnt = wksp_aligned_footprint / page_sz;
     495          99 :   }
     496             : 
     497           3 :   validate( topo );
     498           3 : }

Generated by: LCOV version 1.14