From 4f64286321162f6919abc2cf3a0cc0472e68398c Mon Sep 17 00:00:00 2001 From: Alexander Troosh Date: Tue, 5 Nov 2013 10:16:38 +0100 Subject: lscpu: support non sequentially numbering of CPUs lscpu don't work correctly on my system with: $ cat /sys/devices/system/cpu/possible 0-1,4-5,8-9,12-13 [kzak@redhat.com: - coding style, - add commit message - add real_cpu_num() macro, - fix functions where we need idx as well as CPU number] Signed-off-by: Karel Zak --- sys-utils/lscpu.c | 133 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 49 deletions(-) (limited to 'sys-utils/lscpu.c') diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c index 992726c45..8f14b3af2 100644 --- a/sys-utils/lscpu.c +++ b/sys-utils/lscpu.c @@ -161,6 +161,21 @@ struct lscpu_desc { cpu_set_t *present; /* mask with present CPUs */ cpu_set_t *online; /* mask with online CPUs */ + int nthreads; /* number of online threads */ + + int ncaches; + struct cpu_cache *caches; + + /* + * All maps are sequentially indexed (0..ncpuspos), the array index + * does not have match with cpuX number as presented by kernel. You + * have to use real_cpu_num() to get the real cpuX number. + * + * For example, the possible system CPUs are: 1,3,5, it means that + * ncpuspos=3, so all arrays are in range 0..3. + */ + int *idx2cpunum; /* mapping index to CPU num */ + int nnodes; /* number of NUMA modes */ cpu_set_t **nodemaps; /* array with NUMA nodes */ @@ -179,11 +194,6 @@ struct lscpu_desc { int ncores; /* number of all online cores */ cpu_set_t **coremaps; /* unique thread_siblings */ - int nthreads; /* number of online threads */ - - int ncaches; - struct cpu_cache *caches; - int *polarization; /* cpu polarization */ int *addresses; /* physical cpu addresses */ int *configured; /* cpu configured */ @@ -218,6 +228,8 @@ static int maxcpus; /* size in bits of kernel cpu mask */ ((_d) && (_d)->present ? \ CPU_ISSET_S((_cpu), CPU_ALLOC_SIZE(maxcpus), (_d)->present) : 0) +#define real_cpu_num(_d, _i) ((_d)->idx2cpunum[(_i)]) + /* * IDs */ @@ -417,7 +429,15 @@ read_basicinfo(struct lscpu_desc *desc, struct lscpu_modifier *mod) if (path_exist(_PATH_SYS_SYSTEM "/cpu/possible")) { cpu_set_t *tmp = path_read_cpulist(maxcpus, _PATH_SYS_SYSTEM "/cpu/possible"); + int num, idx; + desc->ncpuspos = CPU_COUNT_S(setsize, tmp); + desc->idx2cpunum = xcalloc(desc->ncpuspos, sizeof(int)); + + for (num = 0, idx = 0; num < maxcpus; num++) { + if (CPU_ISSET(num, tmp)) + desc->idx2cpunum[idx++] = num; + } cpuset_free(tmp); } else err(EXIT_FAILURE, _("failed to determine number of CPUs: %s"), @@ -671,9 +691,10 @@ static int add_cpuset_to_array(cpu_set_t **ary, int *items, cpu_set_t *set) } static void -read_topology(struct lscpu_desc *desc, int num) +read_topology(struct lscpu_desc *desc, int idx) { cpu_set_t *thread_siblings, *core_siblings, *book_siblings; + int num = real_cpu_num(desc, idx); if (!path_exist(_PATH_SYS_CPU "/cpu%d/topology/thread_siblings", num)) return; @@ -683,10 +704,9 @@ read_topology(struct lscpu_desc *desc, int num) core_siblings = path_read_cpuset(maxcpus, _PATH_SYS_CPU "/cpu%d/topology/core_siblings", num); book_siblings = NULL; - if (path_exist(_PATH_SYS_CPU "/cpu%d/topology/book_siblings", num)) { + if (path_exist(_PATH_SYS_CPU "/cpu%d/topology/book_siblings", num)) book_siblings = path_read_cpuset(maxcpus, _PATH_SYS_CPU "/cpu%d/topology/book_siblings", num); - } if (!desc->coremaps) { int nbooks, nsockets, ncores, nthreads; @@ -739,10 +759,12 @@ read_topology(struct lscpu_desc *desc, int num) if (book_siblings) add_cpuset_to_array(desc->bookmaps, &desc->nbooks, book_siblings); } + static void -read_polarization(struct lscpu_desc *desc, int num) +read_polarization(struct lscpu_desc *desc, int idx) { char mode[64]; + int num = real_cpu_num(desc, idx); if (desc->dispatching < 0) return; @@ -752,57 +774,65 @@ read_polarization(struct lscpu_desc *desc, int num) desc->polarization = xcalloc(desc->ncpuspos, sizeof(int)); path_read_str(mode, sizeof(mode), _PATH_SYS_CPU "/cpu%d/polarization", num); if (strncmp(mode, "vertical:low", sizeof(mode)) == 0) - desc->polarization[num] = POLAR_VLOW; + desc->polarization[idx] = POLAR_VLOW; else if (strncmp(mode, "vertical:medium", sizeof(mode)) == 0) - desc->polarization[num] = POLAR_VMEDIUM; + desc->polarization[idx] = POLAR_VMEDIUM; else if (strncmp(mode, "vertical:high", sizeof(mode)) == 0) - desc->polarization[num] = POLAR_VHIGH; + desc->polarization[idx] = POLAR_VHIGH; else if (strncmp(mode, "horizontal", sizeof(mode)) == 0) - desc->polarization[num] = POLAR_HORIZONTAL; + desc->polarization[idx] = POLAR_HORIZONTAL; else - desc->polarization[num] = POLAR_UNKNOWN; + desc->polarization[idx] = POLAR_UNKNOWN; } static void -read_address(struct lscpu_desc *desc, int num) +read_address(struct lscpu_desc *desc, int idx) { + int num = real_cpu_num(desc, idx); + if (!path_exist(_PATH_SYS_CPU "/cpu%d/address", num)) return; if (!desc->addresses) desc->addresses = xcalloc(desc->ncpuspos, sizeof(int)); - desc->addresses[num] = path_read_s32(_PATH_SYS_CPU "/cpu%d/address", num); + desc->addresses[idx] = path_read_s32(_PATH_SYS_CPU "/cpu%d/address", num); } static void -read_configured(struct lscpu_desc *desc, int num) +read_configured(struct lscpu_desc *desc, int idx) { + int num = real_cpu_num(desc, idx); + if (!path_exist(_PATH_SYS_CPU "/cpu%d/configure", num)) return; if (!desc->configured) desc->configured = xcalloc(desc->ncpuspos, sizeof(int)); - desc->configured[num] = path_read_s32(_PATH_SYS_CPU "/cpu%d/configure", num); + desc->configured[idx] = path_read_s32(_PATH_SYS_CPU "/cpu%d/configure", num); } static void -read_max_mhz(struct lscpu_desc *desc, int num) +read_max_mhz(struct lscpu_desc *desc, int idx) { + int num = real_cpu_num(desc, idx); + if (!path_exist(_PATH_SYS_CPU "/cpu%d/cpufreq/cpuinfo_max_freq", num)) return; if (!desc->maxmhz) desc->maxmhz = xcalloc(desc->ncpuspos, sizeof(char *)); - xasprintf(&(desc->maxmhz[num]), "%.4f", + xasprintf(&(desc->maxmhz[idx]), "%.4f", (float)path_read_s32(_PATH_SYS_CPU "/cpu%d/cpufreq/cpuinfo_max_freq", num) / 1000); } static void -read_min_mhz(struct lscpu_desc *desc, int num) +read_min_mhz(struct lscpu_desc *desc, int idx) { + int num = real_cpu_num(desc, idx); + if (!path_exist(_PATH_SYS_CPU "/cpu%d/cpufreq/cpuinfo_min_freq", num)) return; if (!desc->minmhz) desc->minmhz = xcalloc(desc->ncpuspos, sizeof(char *)); - xasprintf(&(desc->minmhz[num]), "%.4f", + xasprintf(&(desc->minmhz[idx]), "%.4f", (float)path_read_s32(_PATH_SYS_CPU "/cpu%d/cpufreq/cpuinfo_min_freq", num) / 1000); } @@ -817,10 +847,11 @@ cachecmp(const void *a, const void *b) } static void -read_cache(struct lscpu_desc *desc, int num) +read_cache(struct lscpu_desc *desc, int idx) { char buf[256]; int i; + int num = real_cpu_num(desc, idx); if (!desc->ncaches) { while(path_exist(_PATH_SYS_SYSTEM "/cpu/cpu%d/cache/index%d", @@ -903,12 +934,13 @@ read_nodes(struct lscpu_desc *desc) } static char * -get_cell_data(struct lscpu_desc *desc, int cpu, int col, +get_cell_data(struct lscpu_desc *desc, int idx, int col, struct lscpu_modifier *mod, char *buf, size_t bufsz) { size_t setsize = CPU_ALLOC_SIZE(maxcpus); - size_t idx; + size_t i; + int cpu = real_cpu_num(desc, idx); *buf = '\0'; @@ -918,23 +950,23 @@ get_cell_data(struct lscpu_desc *desc, int cpu, int col, break; case COL_CORE: if (cpuset_ary_isset(cpu, desc->coremaps, - desc->ncores, setsize, &idx) == 0) - snprintf(buf, bufsz, "%zd", idx); + desc->ncores, setsize, &i) == 0) + snprintf(buf, bufsz, "%zd", i); break; case COL_SOCKET: if (cpuset_ary_isset(cpu, desc->socketmaps, - desc->nsockets, setsize, &idx) == 0) - snprintf(buf, bufsz, "%zd", idx); + desc->nsockets, setsize, &i) == 0) + snprintf(buf, bufsz, "%zd", i); break; case COL_NODE: if (cpuset_ary_isset(cpu, desc->nodemaps, - desc->nnodes, setsize, &idx) == 0) - snprintf(buf, bufsz, "%zd", idx); + desc->nnodes, setsize, &i) == 0) + snprintf(buf, bufsz, "%zd", i); break; case COL_BOOK: if (cpuset_ary_isset(cpu, desc->bookmaps, - desc->nbooks, setsize, &idx) == 0) - snprintf(buf, bufsz, "%zd", idx); + desc->nbooks, setsize, &i) == 0) + snprintf(buf, bufsz, "%zd", i); break; case COL_CACHE: { @@ -946,8 +978,8 @@ get_cell_data(struct lscpu_desc *desc, int cpu, int col, struct cpu_cache *ca = &desc->caches[j]; if (cpuset_ary_isset(cpu, ca->sharedmaps, - ca->nsharedmaps, setsize, &idx) == 0) { - int x = snprintf(p, sz, "%zd", idx); + ca->nsharedmaps, setsize, &i) == 0) { + int x = snprintf(p, sz, "%zd", i); if (x <= 0 || (size_t) x + 2 >= sz) return NULL; p += x; @@ -963,7 +995,7 @@ get_cell_data(struct lscpu_desc *desc, int cpu, int col, } case COL_POLARIZATION: if (desc->polarization) { - int x = desc->polarization[cpu]; + int x = desc->polarization[idx]; snprintf(buf, bufsz, "%s", mod->mode == OUTPUT_PARSABLE ? @@ -973,17 +1005,17 @@ get_cell_data(struct lscpu_desc *desc, int cpu, int col, break; case COL_ADDRESS: if (desc->addresses) - snprintf(buf, bufsz, "%d", desc->addresses[cpu]); + snprintf(buf, bufsz, "%d", desc->addresses[idx]); break; case COL_CONFIGURED: if (!desc->configured) break; if (mod->mode == OUTPUT_PARSABLE) snprintf(buf, bufsz, - desc->configured[cpu] ? _("Y") : _("N")); + desc->configured[idx] ? _("Y") : _("N")); else snprintf(buf, bufsz, - desc->configured[cpu] ? _("yes") : _("no")); + desc->configured[idx] ? _("yes") : _("no")); break; case COL_ONLINE: if (!desc->online) @@ -997,11 +1029,11 @@ get_cell_data(struct lscpu_desc *desc, int cpu, int col, break; case COL_MAXMHZ: if (desc->maxmhz) - xstrncpy(buf, desc->maxmhz[cpu], bufsz); + xstrncpy(buf, desc->maxmhz[idx], bufsz); break; case COL_MINMHZ: if (desc->minmhz) - xstrncpy(buf, desc->minmhz[cpu], bufsz); + xstrncpy(buf, desc->minmhz[idx], bufsz); break; } return buf; @@ -1112,12 +1144,13 @@ print_parsable(struct lscpu_desc *desc, int cols[], int ncols, */ for (i = 0; i < desc->ncpuspos; i++) { int c; + int cpu = real_cpu_num(desc, i); - if (!mod->offline && desc->online && !is_cpu_online(desc, i)) + if (!mod->offline && desc->online && !is_cpu_online(desc, cpu)) continue; - if (!mod->online && desc->online && is_cpu_online(desc, i)) + if (!mod->online && desc->online && is_cpu_online(desc, cpu)) continue; - if (desc->present && !is_cpu_present(desc, i)) + if (desc->present && !is_cpu_present(desc, cpu)) continue; for (c = 0; c < ncols; c++) { if (mod->compat && cols[c] == COL_CACHE) { @@ -1159,12 +1192,13 @@ print_readable(struct lscpu_desc *desc, int cols[], int ncols, for (i = 0; i < desc->ncpuspos; i++) { int c; struct tt_line *line; + int cpu = real_cpu_num(desc, i); - if (!mod->offline && desc->online && !is_cpu_online(desc, i)) + if (!mod->offline && desc->online && !is_cpu_online(desc, cpu)) continue; - if (!mod->online && desc->online && is_cpu_online(desc, i)) + if (!mod->online && desc->online && is_cpu_online(desc, cpu)) continue; - if (desc->present && !is_cpu_present(desc, i)) + if (desc->present && !is_cpu_present(desc, cpu)) continue; line = tt_add_line(tt, NULL); @@ -1252,8 +1286,9 @@ print_summary(struct lscpu_desc *desc, struct lscpu_modifier *mod) err(EXIT_FAILURE, _("failed to callocate cpu set")); CPU_ZERO_S(setsize, set); for (i = 0; i < desc->ncpuspos; i++) { - if (!is_cpu_online(desc, i) && is_cpu_present(desc, i)) - CPU_SET_S(i, setsize, set); + int cpu = real_cpu_num(desc, i); + if (!is_cpu_online(desc, cpu) && is_cpu_present(desc, cpu)) + CPU_SET_S(cpu, setsize, set); } print_cpuset(mod->hex ? _("Off-line CPU(s) mask:") : _("Off-line CPU(s) list:"), -- cgit v1.2.3-55-g7522