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_cpu_topo.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 ulong
40 : determine_ht_pair( config_t const * config,
41 : fd_topo_cpus_t const * cpus,
42 : char const * kind,
43 0 : ulong kind_id ) {
44 0 : ulong tile_idx = fd_topo_find_tile( &config->topo, kind, kind_id );
45 0 : if( FD_LIKELY( tile_idx!=ULONG_MAX ) ) {
46 0 : fd_topo_tile_t const * tile = &config->topo.tiles[ tile_idx ];
47 0 : if( FD_LIKELY( tile->cpu_idx!=ULONG_MAX ) ) return cpus->cpu[ tile->cpu_idx ].sibling;
48 0 : }
49 0 : return ULONG_MAX;
50 0 : }
51 :
52 : static int
53 : determine_cpu_used( config_t const * config,
54 0 : ulong cpu_idx ) {
55 0 : if( FD_UNLIKELY( cpu_idx==ULONG_MAX ) ) return 0;
56 :
57 0 : ulong tile_cnt = config->topo.tile_cnt;
58 0 : for( ulong i=0UL; i<tile_cnt; i++ ) {
59 0 : fd_topo_tile_t const * tile = &config->topo.tiles[ i ];
60 0 : if( tile->cpu_idx==cpu_idx ) return 1;
61 0 : }
62 0 : return 0;
63 0 : }
64 :
65 : static configure_result_t
66 : check( config_t const * config,
67 0 : int check_type ) {
68 0 : if( !( check_type==FD_CONFIGURE_CHECK_TYPE_CHECK ||
69 0 : check_type==FD_CONFIGURE_CHECK_TYPE_RUN ) ) CONFIGURE_OK();
70 :
71 0 : fd_topo_cpus_t cpus[1];
72 0 : fd_topo_cpus_init( cpus );
73 :
74 0 : ulong pack_tile_idx = fd_topo_find_tile( &config->topo, "pack", 0UL );
75 0 : ulong pohh_tile_idx = fd_topo_find_tile( &config->topo, "pohh", 0UL );
76 0 : ulong poh_tile_idx = fd_topo_find_tile( &config->topo, "poh", 0UL );
77 :
78 0 : ulong pack_pair = determine_ht_pair( config, cpus, "pack", 0UL );
79 0 : ulong pohh_pair = determine_ht_pair( config, cpus, "pohh", 0UL );
80 0 : ulong poh_pair = determine_ht_pair( config, cpus, "poh", 0UL );
81 :
82 0 : int pack_pair_used = determine_cpu_used( config, pack_pair );
83 0 : int pohh_pair_used = determine_cpu_used( config, pohh_pair );
84 0 : int poh_pair_used = determine_cpu_used( config, poh_pair );
85 :
86 0 : int pack_pair_online = 0;
87 0 : int pohh_pair_online = 0;
88 0 : int poh_pair_online = 0;
89 0 : for( ulong i=0UL; i<cpus->cpu_cnt; i++ ) {
90 0 : if( i==pack_pair && !pack_pair_used ) {
91 0 : if( FD_UNLIKELY( cpus->cpu[ i ].online ) ) pack_pair_online = 1;
92 0 : } else if( i==pohh_pair && !pohh_pair_used ) {
93 0 : if( FD_UNLIKELY( cpus->cpu[ i ].online ) ) pohh_pair_online = 1;
94 0 : } else if( i==poh_pair && !poh_pair_used ) {
95 0 : if( FD_UNLIKELY( cpus->cpu[ i ].online ) ) poh_pair_online = 1;
96 0 : }
97 0 : }
98 :
99 : /* An online-but-unused sibling inside this instance's isolated
100 : cpuset partition is permanently idle, which is about as good as
101 : offline for SMT purposes: no warning needed. */
102 0 : if( FD_UNLIKELY( pack_pair_online && sibling_isolated_idle( config, pack_pair ) ) ) pack_pair_online = 0;
103 0 : if( FD_UNLIKELY( pohh_pair_online && sibling_isolated_idle( config, pohh_pair ) ) ) pohh_pair_online = 0;
104 0 : if( FD_UNLIKELY( poh_pair_online && sibling_isolated_idle( config, poh_pair ) ) ) poh_pair_online = 0;
105 :
106 0 : if( FD_UNLIKELY( pack_pair_used ) ) FD_LOG_WARNING(( "pack cpu %lu has hyperthread pair cpu %lu which is used by another tile. Proceeding but performance may be reduced.", config->topo.tiles[ pack_tile_idx ].cpu_idx, pack_pair ));
107 0 : else if( FD_UNLIKELY( pack_pair_online ) ) FD_LOG_WARNING(( "pack 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.", config->topo.tiles[ pack_tile_idx ].cpu_idx, pack_pair ));
108 0 : if( FD_UNLIKELY( pohh_pair_used ) ) FD_LOG_WARNING(( "pohh cpu %lu has hyperthread pair cpu %lu which is used by another tile. Proceeding but performance may be reduced.", config->topo.tiles[ pohh_tile_idx ].cpu_idx, pohh_pair ));
109 0 : else if( FD_UNLIKELY( pohh_pair_online ) ) FD_LOG_WARNING(( "pohh 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.", config->topo.tiles[ pohh_tile_idx ].cpu_idx, pohh_pair ));
110 0 : if( FD_UNLIKELY( poh_pair_used ) ) FD_LOG_WARNING(( "poh cpu %lu has hyperthread pair cpu %lu which is used by another tile. Proceeding but performance may be reduced.", config->topo.tiles[ poh_tile_idx ].cpu_idx, poh_pair ));
111 0 : else if( FD_UNLIKELY( poh_pair_online ) ) FD_LOG_WARNING(( "poh 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.", config->topo.tiles[ poh_tile_idx ].cpu_idx, poh_pair ));
112 :
113 0 : CONFIGURE_OK();
114 0 : }
115 :
116 : configure_stage_t fd_cfg_stage_hyperthreads = {
117 : .name = NAME,
118 : .always_recreate = 0,
119 : .enabled = NULL,
120 : .init_perm = NULL,
121 : .fini_perm = NULL,
122 : .init = NULL,
123 : .fini = NULL,
124 : .check = check,
125 : };
126 :
127 : #undef NAME
|