Line data Source code
1 : #include "configure.h"
2 :
3 : #define NAME "hyperthreads"
4 :
5 : #include "fd_cpu_isolation.h"
6 : #include "../../../../disco/topo/fd_topob.h"
7 :
8 : #include <errno.h>
9 : #include <fcntl.h>
10 : #include <unistd.h>
11 :
12 : static int
13 : sibling_isolated_idle( config_t const * config,
14 0 : ulong cpu_idx ) {
15 0 : char path[ PATH_MAX ];
16 0 : FD_TEST( fd_cstr_printf_check( path, sizeof(path), NULL, "/sys/fs/cgroup/%s/cpuset.cpus", config->name ) );
17 :
18 0 : int fd = open( path, O_RDONLY );
19 0 : if( FD_UNLIKELY( fd<0 ) ) {
20 0 : if( FD_LIKELY( errno==ENOENT ) ) return 0; /* cpuset stage not configured */
21 0 : FD_LOG_ERR(( "open(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
22 0 : }
23 :
24 0 : char list[ FD_CPU_ISOLATION_LIST_MAX ];
25 0 : long list_len = read( fd, list, sizeof(list)-1UL );
26 0 : if( FD_UNLIKELY( list_len<0L ) ) FD_LOG_ERR(( "read(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
27 0 : if( FD_UNLIKELY( close( fd ) ) ) FD_LOG_ERR(( "close(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
28 0 : list[ list_len ] = '\0';
29 :
30 0 : FD_CPUSET_DECL( partition );
31 0 : if( FD_UNLIKELY( !fd_cpu_isolation_parse_list( partition, list ) ) )
32 0 : FD_LOG_ERR(( "failed to parse `%s` (\"%s\")", path, list ));
33 :
34 0 : if( FD_LIKELY( cpu_idx>=FD_TILE_MAX || !fd_cpuset_test( partition, cpu_idx ) ) ) return 0;
35 :
36 0 : return 1;
37 0 : }
38 :
39 : static configure_result_t
40 : check( config_t const * config,
41 0 : int check_type ) {
42 0 : if( !( check_type==FD_CONFIGURE_CHECK_TYPE_CHECK ||
43 0 : check_type==FD_CONFIGURE_CHECK_TYPE_RUN ) ) CONFIGURE_OK();
44 :
45 0 : fd_topo_cpus_t cpus[1];
46 0 : fd_topo_cpus_init( cpus );
47 :
48 0 : fd_topo_t const * topo = &config->topo;
49 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
50 0 : fd_topo_tile_t const * tile = &topo->tiles[ i ];
51 0 : if( FD_LIKELY( tile->kind_id || strcmp( tile->name, "pack" ) ) ) continue;
52 :
53 : /* A floating tile (efficient layout mode) shares its cores with
54 : the other floaters, so an idle sibling buys it nothing */
55 0 : if( FD_UNLIKELY( tile->cpu_idx>=cpus->cpu_cnt || tile->floats ) ) continue;
56 0 : ulong pair = cpus->cpu[ tile->cpu_idx ].sibling;
57 0 : if( FD_UNLIKELY( pair>=cpus->cpu_cnt ) ) continue;
58 :
59 0 : int pair_used = 0;
60 0 : for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
61 0 : fd_topo_tile_t const * other = &topo->tiles[ j ];
62 0 : pair_used |= other->cpu_idx==pair && !( fd_topob_tile_class( other->name ) & FD_TOPOB_TILE_STARTUP );
63 0 : }
64 :
65 : /* An online-but-unused sibling inside this instance's isolated
66 : cpuset partition is permanently idle, which is about as good as
67 : offline for SMT purposes: no warning needed. */
68 0 : int pair_online = !pair_used && cpus->cpu[ pair ].online && !sibling_isolated_idle( config, pair );
69 :
70 0 : if( FD_UNLIKELY( pair_used ) ) FD_LOG_WARNING(( "%s cpu %lu has hyperthread pair cpu %lu which is used by another tile. Proceeding but performance may be reduced.", tile->name, tile->cpu_idx, pair ));
71 0 : else if( FD_UNLIKELY( pair_online ) ) FD_LOG_WARNING(( "%s cpu %lu has hyperthread pair cpu %lu which should be offline or in the isolated cpuset partition (`configure init cpuset`). Proceeding but performance may be reduced.", tile->name, tile->cpu_idx, pair ));
72 0 : }
73 :
74 : /* One summary line for the other hot tiles sharing a core */
75 0 : static char const * const HOT[] = { "replay", "shred", "execle", "execrp", "motor" };
76 0 : char pairs[ 512 ] = "";
77 0 : ulong len = 0UL;
78 0 : ulong cnt = 0UL;
79 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
80 0 : fd_topo_tile_t const * tile = &topo->tiles[ i ];
81 0 : int hot = 0;
82 0 : for( ulong k=0UL; k<sizeof(HOT)/sizeof(HOT[0]); k++ ) hot |= !strcmp( tile->name, HOT[ k ] );
83 0 : if( !hot || tile->floats || tile->cpu_idx>=cpus->cpu_cnt ) continue;
84 0 : ulong pair = cpus->cpu[ tile->cpu_idx ].sibling;
85 0 : for( ulong j=0UL; j<topo->tile_cnt && pair<cpus->cpu_cnt; j++ ) {
86 0 : fd_topo_tile_t const * other = &topo->tiles[ j ];
87 0 : if( other->cpu_idx!=pair || other->floats || ( fd_topob_tile_class( other->name ) & FD_TOPOB_TILE_STARTUP ) ) continue;
88 0 : ulong n = 0UL;
89 0 : if( cnt<8UL ) FD_TEST( fd_cstr_printf_check( pairs+len, sizeof(pairs)-len, &n, " %s:%lu/%s:%lu", tile->name, tile->kind_id, other->name, other->kind_id ) );
90 0 : len += n;
91 0 : cnt++;
92 0 : break;
93 0 : }
94 0 : }
95 0 : if( FD_UNLIKELY( cnt ) ) FD_LOG_NOTICE(( "%lu hot tiles share a physical core with another tile:%s%s", cnt, pairs, cnt>8UL ? " ..." : "" ));
96 :
97 0 : CONFIGURE_OK();
98 0 : }
99 :
100 : configure_stage_t fd_cfg_stage_hyperthreads = {
101 : .name = NAME,
102 : .always_recreate = 0,
103 : .enabled = NULL,
104 : .init_perm = NULL,
105 : .fini_perm = NULL,
106 : .init = NULL,
107 : .fini = NULL,
108 : .check = check,
109 : };
110 :
111 : #undef NAME
|