Line data Source code
1 : #include "fd_topo.h"
2 :
3 : #include "../fd_disco_base.h"
4 : #include "../metrics/fd_metrics.h"
5 : #include "../quic/fd_tpu.h"
6 : #include "../../util/wksp/fd_wksp_private.h"
7 : #include "../../util/shmem/fd_shmem_private.h"
8 :
9 : #include <stdio.h>
10 : #include <errno.h>
11 : #include <unistd.h>
12 : #include <sys/stat.h>
13 :
14 : void
15 : fd_topo_join_workspace( fd_topo_t * topo,
16 : fd_topo_wksp_t * wksp,
17 0 : int mode ) {
18 0 : char name[ PATH_MAX ];
19 0 : FD_TEST( fd_cstr_printf_check( name, PATH_MAX, NULL, "%s_%s.wksp", topo->app_name, wksp->name ) );
20 :
21 0 : wksp->wksp = fd_wksp_join( fd_shmem_join( name, mode, NULL, NULL, NULL ) );
22 0 : if( FD_UNLIKELY( !wksp->wksp ) ) FD_LOG_ERR(( "fd_wksp_join failed" ));
23 0 : }
24 :
25 : FD_FN_PURE static int
26 0 : tile_needs_wksp( fd_topo_t const * topo, fd_topo_tile_t * tile, ulong wksp_id ) {
27 0 : int mode = -1;
28 0 : for( ulong i=0UL; i<tile->uses_obj_cnt; i++ ) {
29 0 : if( FD_UNLIKELY( topo->objs[ tile->uses_obj_id[ i ] ].wksp_id==wksp_id ) ) {
30 0 : mode = fd_int_max( mode, tile->uses_obj_mode[ i ] );
31 0 : }
32 0 : }
33 0 : return mode;
34 0 : }
35 :
36 : void
37 : fd_topo_join_tile_workspaces( fd_topo_t * topo,
38 0 : fd_topo_tile_t * tile ) {
39 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
40 0 : int needs_wksp = tile_needs_wksp( topo, tile, i );
41 0 : if( FD_LIKELY( -1!=needs_wksp ) ) {
42 0 : fd_topo_join_workspace( topo, &topo->workspaces[ i ], needs_wksp );
43 0 : }
44 0 : }
45 0 : }
46 :
47 : void
48 : fd_topo_join_workspaces( fd_topo_t * topo,
49 0 : int mode ) {
50 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
51 0 : fd_topo_join_workspace( topo, &topo->workspaces[ i ], mode );
52 0 : }
53 0 : }
54 :
55 : void
56 : fd_topo_leave_workspace( fd_topo_t * topo,
57 0 : fd_topo_wksp_t * wksp ) {
58 0 : (void)topo;
59 :
60 0 : if( FD_LIKELY( wksp->wksp ) ) {
61 0 : if( FD_UNLIKELY( fd_wksp_detach( wksp->wksp ) ) ) FD_LOG_ERR(( "fd_wksp_detach failed" ));
62 0 : wksp->wksp = NULL;
63 0 : wksp->known_footprint = 0UL;
64 0 : wksp->total_footprint = 0UL;
65 0 : }
66 0 : }
67 :
68 : void
69 0 : fd_topo_leave_workspaces( fd_topo_t * topo ) {
70 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
71 0 : fd_topo_leave_workspace( topo, &topo->workspaces[ i ] );
72 0 : }
73 0 : }
74 :
75 : extern char fd_shmem_private_base[ FD_SHMEM_PRIVATE_BASE_MAX ];
76 :
77 : int
78 : fd_topo_create_workspace( fd_topo_t * topo,
79 : fd_topo_wksp_t * wksp,
80 0 : int update_existing ) {
81 0 : char name[ PATH_MAX ];
82 0 : FD_TEST( fd_cstr_printf_check( name, PATH_MAX, NULL, "%s_%s.wksp", topo->app_name, wksp->name ) );
83 :
84 0 : ulong sub_page_cnt[ 1 ] = { wksp->page_cnt };
85 0 : ulong sub_cpu_idx [ 1 ] = { fd_shmem_cpu_idx( wksp->numa_idx ) };
86 :
87 0 : int err;
88 0 : if( FD_UNLIKELY( update_existing ) ) {
89 0 : err = fd_shmem_update_multi( name, wksp->page_sz, 1, sub_page_cnt, sub_cpu_idx, S_IRUSR | S_IWUSR ); /* logs details */
90 0 : } else {
91 0 : err = fd_shmem_create_multi( name, wksp->page_sz, 1, sub_page_cnt, sub_cpu_idx, S_IRUSR | S_IWUSR ); /* logs details */
92 0 : }
93 0 : if( FD_UNLIKELY( err && errno==ENOMEM ) ) return -1;
94 0 : else if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_shmem_create_multi failed" ));
95 :
96 0 : void * shmem = fd_shmem_join( name, FD_SHMEM_JOIN_MODE_READ_WRITE, NULL, NULL, NULL ); /* logs details */
97 :
98 0 : void * wkspmem = fd_wksp_new( shmem, name, 0U, wksp->part_max, wksp->total_footprint ); /* logs details */
99 0 : if( FD_UNLIKELY( !wkspmem ) ) FD_LOG_ERR(( "fd_wksp_new failed" ));
100 :
101 0 : fd_wksp_t * join = fd_wksp_join( wkspmem );
102 0 : if( FD_UNLIKELY( !join ) ) FD_LOG_ERR(( "fd_wksp_join failed" ));
103 :
104 : /* Footprint has been predetermined so that this alloc() call must
105 : succeed inside the data region. The difference between total_footprint
106 : and known_footprint is given to "loose" data, that may be dynamically
107 : allocated out of the workspace at runtime. */
108 0 : if( FD_LIKELY( wksp->known_footprint ) ) {
109 0 : ulong offset = fd_wksp_alloc( join, fd_topo_workspace_align(), wksp->known_footprint, 1UL );
110 0 : if( FD_UNLIKELY( !offset ) ) FD_LOG_ERR(( "fd_wksp_alloc failed" ));
111 :
112 : /* gaddr_lo is the start of the workspace data region that can be
113 : given out in response to wksp alloc requests. We rely on an
114 : implicit assumption everywhere that the bytes we are given by
115 : this single allocation will be at gaddr_lo, so that we can find
116 : them, so we verify this here for paranoia in case the workspace
117 : alloc implementation changes. */
118 0 : if( FD_UNLIKELY( fd_ulong_align_up( ((struct fd_wksp_private*)join)->gaddr_lo, fd_topo_workspace_align() ) != offset ) )
119 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 ));
120 0 : }
121 :
122 0 : fd_wksp_leave( join );
123 :
124 0 : if( FD_UNLIKELY( fd_shmem_leave( shmem, NULL, NULL ) ) ) /* logs details */
125 0 : FD_LOG_ERR(( "fd_shmem_leave failed" ));
126 :
127 0 : return 0;
128 0 : }
129 :
130 : void
131 : fd_topo_wksp_apply( fd_topo_t * topo,
132 : fd_topo_wksp_t * wksp,
133 0 : void (* fn )( fd_topo_t const * topo, fd_topo_obj_t const * obj ) ) {
134 0 : for( ulong i=0UL; i<topo->obj_cnt; i++ ) {
135 0 : fd_topo_obj_t * obj = &topo->objs[ i ];
136 0 : if( FD_LIKELY( obj->wksp_id!=wksp->id ) ) continue;
137 0 : fn( topo, obj );
138 0 : }
139 0 : }
140 :
141 : void
142 : fd_topo_workspace_fill( fd_topo_t * topo,
143 0 : fd_topo_wksp_t * wksp ) {
144 0 : for( ulong i=0UL; i<topo->link_cnt; i++ ) {
145 0 : fd_topo_link_t * link = &topo->links[ i ];
146 :
147 0 : if( FD_UNLIKELY( topo->objs[ link->mcache_obj_id ].wksp_id!=wksp->id ) ) continue;
148 0 : link->mcache = fd_mcache_join( fd_topo_obj_laddr( topo, link->mcache_obj_id ) );
149 0 : FD_TEST( link->mcache );
150 :
151 0 : if( FD_LIKELY( link->is_reasm ) ) {
152 0 : if( FD_UNLIKELY( topo->objs[ link->reasm_obj_id].wksp_id!=wksp->id ) ) continue;
153 0 : link->reasm = fd_tpu_reasm_join( fd_topo_obj_laddr( topo, link->reasm_obj_id ) );
154 0 : FD_TEST( link->reasm );
155 0 : } else if ( link->mtu ) {
156 0 : if( FD_UNLIKELY( topo->objs[ link->dcache_obj_id ].wksp_id!=wksp->id ) ) continue;
157 0 : link->dcache = fd_dcache_join( fd_topo_obj_laddr( topo, link->dcache_obj_id ) );
158 0 : FD_TEST( link->dcache );
159 0 : }
160 0 : }
161 :
162 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
163 0 : fd_topo_tile_t * tile = &topo->tiles[ i ];
164 :
165 0 : if( FD_LIKELY( topo->objs[ tile->metrics_obj_id ].wksp_id==wksp->id ) ) {
166 0 : tile->metrics = fd_metrics_join( fd_topo_obj_laddr( topo, tile->metrics_obj_id ) );
167 0 : FD_TEST( tile->metrics );
168 0 : }
169 :
170 0 : for( ulong j=0UL; j<tile->in_cnt; j++ ) {
171 0 : if( FD_UNLIKELY( topo->objs[ tile->in_link_fseq_obj_id[ j ] ].wksp_id!=wksp->id ) ) continue;
172 0 : tile->in_link_fseq[ j ] = fd_fseq_join( fd_topo_obj_laddr( topo, tile->in_link_fseq_obj_id[ j ] ) );
173 0 : FD_TEST( tile->in_link_fseq[ j ] );
174 0 : }
175 0 : }
176 0 : }
177 :
178 : void
179 : fd_topo_fill_tile( fd_topo_t * topo,
180 0 : fd_topo_tile_t * tile ) {
181 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
182 0 : if( FD_UNLIKELY( -1!=tile_needs_wksp( topo, tile, i ) ) )
183 0 : fd_topo_workspace_fill( topo, &topo->workspaces[ i ] );
184 0 : }
185 0 : }
186 :
187 : void
188 0 : fd_topo_fill( fd_topo_t * topo ) {
189 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
190 0 : fd_topo_workspace_fill( topo, &topo->workspaces[ i ] );
191 0 : }
192 0 : }
193 :
194 : FD_FN_CONST static ulong
195 0 : fd_topo_tile_extra_huge_pages( fd_topo_tile_t const * tile ) {
196 0 : (void)tile;
197 :
198 : /* Every tile maps an additional set of pages for the stack. */
199 0 : ulong extra_pages = (FD_TILE_PRIVATE_STACK_SZ/FD_SHMEM_HUGE_PAGE_SZ)+2UL;
200 :
201 0 : if( FD_UNLIKELY( !strcmp( tile->name, "replay" ) ) ) {
202 : /* TODO: This is extremely gross. Replay tile spawns a bunch of
203 : extra threads which also require stack space. These huge
204 : pages need to be reserved as well. */
205 0 : extra_pages += tile->replay.tpool_thread_count*((FD_TILE_PRIVATE_STACK_SZ/FD_SHMEM_HUGE_PAGE_SZ)+2UL);
206 0 : }
207 :
208 0 : return extra_pages;
209 0 : }
210 :
211 : FD_FN_PURE static ulong
212 0 : fd_topo_tile_extra_normal_pages( fd_topo_tile_t const * tile ) {
213 0 : ulong key_pages = 0UL;
214 0 : if( FD_UNLIKELY( !strcmp( tile->name, "sign" ) ||
215 0 : !strcmp( tile->name, "shred" ) ||
216 0 : !strcmp( tile->name, "poh" ) ||
217 0 : !strcmp( tile->name, "quic" ) ||
218 :
219 0 : !strcmp( tile->name, "gossip" ) ||
220 0 : !strcmp( tile->name, "repair" ) ||
221 0 : !strcmp( tile->name, "pohi" ) ||
222 0 : !strcmp( tile->name, "storei" ) ) ) {
223 : /* Certain tiles using fd_keyload_load need normal pages to hold
224 : key material. */
225 0 : key_pages = 5UL;
226 0 : }
227 :
228 : /* All tiles lock one normal page for the fd_log shared lock. */
229 0 : return key_pages + 1UL;
230 0 : }
231 :
232 : FD_FN_PURE static ulong
233 : fd_topo_mlock_max_tile1( fd_topo_t const * topo,
234 0 : fd_topo_tile_t * tile ) {
235 0 : ulong tile_mem = 0UL;
236 :
237 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
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 * 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 * 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 * 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 * 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 * topo ) {
309 0 : ulong result = 0UL;
310 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
311 0 : result += topo->workspaces[ i ].page_cnt * topo->workspaces[ i ].page_sz;
312 0 : }
313 0 : return result;
314 0 : }
315 :
316 : static void
317 0 : fd_topo_mem_sz_string( ulong sz, char out[static 24] ) {
318 0 : if( FD_LIKELY( sz >= FD_SHMEM_GIGANTIC_PAGE_SZ ) ) {
319 0 : FD_TEST( fd_cstr_printf_check( out, 24, NULL, "%lu GiB", sz / (1 << 30) ) );
320 0 : } else {
321 0 : FD_TEST( fd_cstr_printf_check( out, 24, NULL, "%lu MiB", sz / (1 << 20) ) );
322 0 : }
323 0 : }
324 :
325 : void
326 : fd_topo_print_log( int stdout,
327 0 : fd_topo_t * topo ) {
328 0 : char message[ 16UL*4096UL ] = {0}; /* Same as FD_LOG_BUF_SZ */
329 :
330 0 : char * cur = message;
331 0 : ulong remaining = sizeof(message) - 1; /* Leave one character at the end to ensure NUL terminated */
332 :
333 0 : #define PRINT( ... ) do { \
334 0 : int n = snprintf( cur, remaining, __VA_ARGS__ ); \
335 0 : if( FD_UNLIKELY( n < 0 ) ) FD_LOG_ERR(( "snprintf failed" )); \
336 0 : if( FD_UNLIKELY( (ulong)n >= remaining ) ) FD_LOG_ERR(( "snprintf overflow" )); \
337 0 : remaining -= (ulong)n; \
338 0 : cur += n; \
339 0 : } while( 0 )
340 :
341 0 : PRINT( "\nSUMMARY\n" );
342 :
343 : /* The logic to compute number of stack pages is taken from
344 : fd_tile_thread.cxx, in function fd_topo_tile_stack_join, and this
345 : should match that. */
346 0 : ulong stack_pages = topo->tile_cnt * FD_SHMEM_HUGE_PAGE_SZ * ((FD_TILE_PRIVATE_STACK_SZ/FD_SHMEM_HUGE_PAGE_SZ)+2UL);
347 :
348 : /* The logic to map these private pages into memory is in utility.c,
349 : under fd_keyload_load, and the amount of pages should be kept in
350 : sync. */
351 0 : ulong private_key_pages = 5UL * FD_SHMEM_NORMAL_PAGE_SZ;
352 0 : ulong total_bytes = fd_topo_mlock( topo ) + stack_pages + private_key_pages;
353 :
354 0 : PRINT(" %23s: %lu\n", "Total Tiles", topo->tile_cnt );
355 0 : PRINT(" %23s: %lu bytes (%lu GiB + %lu MiB + %lu KiB)\n",
356 0 : "Total Memory Locked",
357 0 : total_bytes,
358 0 : total_bytes / (1 << 30),
359 0 : (total_bytes % (1 << 30)) / (1 << 20),
360 0 : (total_bytes % (1 << 20)) / (1 << 10) );
361 :
362 0 : ulong required_gigantic_pages = 0UL;
363 0 : ulong required_huge_pages = 0UL;
364 :
365 0 : ulong numa_node_cnt = fd_shmem_numa_cnt();
366 0 : for( ulong i=0UL; i<numa_node_cnt; i++ ) {
367 0 : required_gigantic_pages += fd_topo_gigantic_page_cnt( topo, i );
368 0 : required_huge_pages += fd_topo_huge_page_cnt( topo, i, 0 );
369 0 : }
370 0 : PRINT(" %23s: %lu\n", "Required Gigantic Pages", required_gigantic_pages );
371 0 : PRINT(" %23s: %lu\n", "Required Huge Pages", required_huge_pages );
372 0 : PRINT(" %23s: %lu\n", "Required Normal Pages", fd_topo_normal_page_cnt( topo ) );
373 0 : for( ulong i=0UL; i<numa_node_cnt; i++ ) {
374 0 : PRINT(" %23s (NUMA node %lu): %lu\n", "Required Gigantic Pages", i, fd_topo_gigantic_page_cnt( topo, i ) );
375 0 : PRINT(" %23s (NUMA node %lu): %lu\n", "Required Huge Pages", i, fd_topo_huge_page_cnt( topo, i, 0 ) );
376 0 : }
377 :
378 0 : char agave_affinity[ 4096 ];
379 0 : ulong offset = 0UL;
380 0 : for( ulong i=0UL; i<topo->agave_affinity_cnt; i++ ) {
381 0 : ulong sz;
382 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 ] ) );
383 0 : else FD_TEST( fd_cstr_printf_check( agave_affinity+offset, 4096-offset, &sz, "%lu", topo->agave_affinity_cpu_idx[ i ] ) );
384 0 : offset += sz;
385 0 : }
386 0 : PRINT(" %23s: %s\n", "Agave Affinity", agave_affinity );
387 :
388 0 : PRINT( "\nWORKSPACES\n");
389 0 : for( ulong i=0UL; i<topo->wksp_cnt; i++ ) {
390 0 : fd_topo_wksp_t * wksp = &topo->workspaces[ i ];
391 :
392 0 : char size[ 24 ];
393 0 : fd_topo_mem_sz_string( wksp->page_sz * wksp->page_cnt, size );
394 0 : PRINT( " %2lu (%7s): %12s page_cnt=%lu page_sz=%-8s numa_idx=%-2lu footprint=%-10lu loose=%lu\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 );
395 0 : }
396 :
397 0 : PRINT( "\nLINKS\n" );
398 0 : for( ulong i=0UL; i<topo->link_cnt; i++ ) {
399 0 : fd_topo_link_t * link = &topo->links[ i ];
400 :
401 0 : char size[ 24 ];
402 0 : if( FD_UNLIKELY( !strcmp( link->name, "quic_verify" ) ) ) {
403 0 : fd_topo_mem_sz_string( fd_tpu_reasm_footprint( link->depth, link->burst ), size );
404 0 : } else {
405 0 : fd_topo_mem_sz_string( fd_dcache_req_data_sz( link->mtu, link->depth, link->burst, 1 ), size );
406 0 : }
407 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 );
408 0 : }
409 :
410 0 : #define PRINTIN( ... ) do { \
411 0 : int n = snprintf( cur_in, remaining_in, __VA_ARGS__ ); \
412 0 : if( FD_UNLIKELY( n < 0 ) ) FD_LOG_ERR(( "snprintf failed" )); \
413 0 : if( FD_UNLIKELY( (ulong)n >= remaining_in ) ) FD_LOG_ERR(( "snprintf overflow" )); \
414 0 : remaining_in -= (ulong)n; \
415 0 : cur_in += n; \
416 0 : } while( 0 )
417 :
418 0 : #define PRINTOUT( ... ) do { \
419 0 : int n = snprintf( cur_out, remaining_in, __VA_ARGS__ ); \
420 0 : if( FD_UNLIKELY( n < 0 ) ) FD_LOG_ERR(( "snprintf failed" )); \
421 0 : if( FD_UNLIKELY( (ulong)n >= remaining_out ) ) FD_LOG_ERR(( "snprintf overflow" )); \
422 0 : remaining_out -= (ulong)n; \
423 0 : cur_out += n; \
424 0 : } while( 0 )
425 :
426 0 : PRINT( "\nTILES\n" );
427 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
428 0 : fd_topo_tile_t * tile = &topo->tiles[ i ];
429 :
430 0 : char in[ 256 ] = {0};
431 0 : char * cur_in = in;
432 0 : ulong remaining_in = sizeof( in ) - 1;
433 :
434 0 : for( ulong j=0UL; j<tile->in_cnt; j++ ) {
435 0 : if( FD_LIKELY( j != 0 ) ) PRINTIN( ", " );
436 0 : if( FD_LIKELY( tile->in_link_reliable[ j ] ) ) PRINTIN( "%2lu", tile->in_link_id[ j ] );
437 0 : else PRINTIN( "%2ld", (long)-tile->in_link_id[ j ] );
438 0 : }
439 :
440 0 : char out[ 256 ] = {0};
441 0 : char * cur_out = out;
442 0 : ulong remaining_out = sizeof( out ) - 1;
443 :
444 0 : for( ulong j=0UL; j<tile->out_cnt; j++ ) {
445 0 : if( FD_LIKELY( j != 0 ) ) PRINTOUT( ", " );
446 0 : PRINTOUT( "%2lu", tile->out_link_id[ j ] );
447 0 : }
448 :
449 0 : char size[ 24 ];
450 0 : fd_topo_mem_sz_string( fd_topo_mlock_max_tile1( topo, tile ), size );
451 0 : PRINT( " %2lu (%7s): %12s kind_id=%-2lu wksp_id=%-2lu cpu_idx=%-2lu in=[%s] out=[%s]", i, size, tile->name, tile->kind_id, topo->objs[ tile->tile_obj_id ].wksp_id, tile->cpu_idx, in, out );
452 0 : if( FD_LIKELY( i != topo->tile_cnt-1 ) ) PRINT( "\n" );
453 0 : }
454 :
455 0 : if( FD_UNLIKELY( stdout ) ) FD_LOG_STDOUT(( "%s\n", message ));
456 0 : else FD_LOG_NOTICE(( "%s", message ));
457 0 : }
|