diff --git a/hwloc/topology-linux.c b/hwloc/topology-linux.c index 201153580..e0e212ba8 100644 --- a/hwloc/topology-linux.c +++ b/hwloc/topology-linux.c @@ -4424,6 +4424,13 @@ look_sysfsnode(struct hwloc_topology *topology, * sysfs CPU frequencies for cpukinds */ +struct hwloc_linux_cpukinds_by_pu { + unsigned pu; + unsigned long max_freq; + unsigned long base_freq; + unsigned long capacity; +}; + struct hwloc_linux_cpukinds { struct hwloc_linux_cpukind { unsigned long value; @@ -4610,6 +4617,8 @@ static int look_sysfscpukinds(struct hwloc_topology *topology, struct hwloc_linux_backend_data_s *data) { + int nr_pus; + struct hwloc_linux_cpukinds_by_pu *by_pu; struct hwloc_linux_cpukinds cpufreqs_max, cpufreqs_base, cpu_capacity; int max_without_basefreq = 0; /* any cpu where we have maxfreq without basefreq? */ char str[293]; @@ -4617,7 +4626,7 @@ look_sysfscpukinds(struct hwloc_topology *topology, hwloc_bitmap_t atom_pmu_set, core_pmu_set; int maxfreq_enabled = -1; /* -1 means adjust (default), 0 means ignore, 1 means enforce */ unsigned adjust_max = 10; - int i; + int pu, i; env = getenv("HWLOC_CPUKINDS_MAXFREQ"); if (env) { @@ -4637,24 +4646,45 @@ look_sysfscpukinds(struct hwloc_topology *topology, hwloc_debug("linux/cpufreq: max frequency values will be adjusted by up to %u%%\n", adjust_max); - /* look at the PU base+max frequency */ - hwloc_linux_cpukinds_init(&cpufreqs_max); - hwloc_linux_cpukinds_init(&cpufreqs_base); - hwloc_bitmap_foreach_begin(i, topology->levels[0][0]->cpuset) { - unsigned maxfreq = 0, basefreq = 0; + nr_pus = hwloc_bitmap_weight(topology->levels[0][0]->cpuset); + assert(nr_pus > 0); + by_pu = calloc(nr_pus, sizeof(*by_pu)); + if (!by_pu) + return -1; + + /* gather all sysfs info in the by_pu array */ + i = 0; + hwloc_bitmap_foreach_begin(pu, topology->levels[0][0]->cpuset) { + unsigned maxfreq = 0, basefreq = 0, capacity = 0;; + by_pu[i].pu = pu; + /* cpuinfo_max_freq is the hardware max. scaling_max_freq is the software policy current max */ sprintf(str, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", i); if (hwloc_read_path_as_uint(str, &maxfreq, data->root_fd) >= 0) - if (maxfreq) - hwloc_linux_cpukinds_add(&cpufreqs_max, i, maxfreq/1000); + by_pu[i].max_freq = maxfreq; /* base_frequency is intel_pstate specific */ sprintf(str, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", i); if (hwloc_read_path_as_uint(str, &basefreq, data->root_fd) >= 0) - if (basefreq) - hwloc_linux_cpukinds_add(&cpufreqs_base, i, basefreq/1000); + by_pu[i].base_freq = basefreq; if (maxfreq && !basefreq) max_without_basefreq = 1; + /* capacity */ + sprintf(str, "/sys/devices/system/cpu/cpu%d/cpu_capacity", i); + if (hwloc_read_path_as_uint(str, &capacity, data->root_fd) >= 0) + by_pu[i].capacity = capacity; + i++; } hwloc_bitmap_foreach_end(); + assert(i == nr_pus); + + /* now store base+max frequency */ + hwloc_linux_cpukinds_init(&cpufreqs_max); + hwloc_linux_cpukinds_init(&cpufreqs_base); + for(i=0; ilevels[0][0]->cpuset) { - unsigned capacity; - sprintf(str, "/sys/devices/system/cpu/cpu%d/cpu_capacity", i); - if (hwloc_read_path_as_uint(str, &capacity, data->root_fd) >= 0) - hwloc_linux_cpukinds_add(&cpu_capacity, i, capacity); - } hwloc_bitmap_foreach_end(); + for(i=0; iroot_fd); core_pmu_set = hwloc__alloc_read_path_as_cpulist("/sys/devices/cpu_core/cpus", data->root_fd);