]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: support non sequentially numbering of CPUs
authorAlexander Troosh <trush@yandex.ru>
Tue, 5 Nov 2013 09:16:38 +0000 (10:16 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 5 Nov 2013 11:46:03 +0000 (12:46 +0100)
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 <kzak@redhat.com>
sys-utils/lscpu.1
sys-utils/lscpu.c

index 3ce82171aaec6a60a8b1210dfef02c3e771b3f95..bf81a44dfb7c4528f6242bfa2ab47f37a7f5ea54 100644 (file)
@@ -29,6 +29,9 @@ Not all columns are supported on all architectures.  If an unsupported column is
 specified, \fBlscpu\fP prints the column but does not provide any data for it.
 
 .SS COLUMNS
+Note that topology elements (core, socket, etc.) use sequential unique ID
+starting from zero, but CPU logical numbers follow kernel where is no guarantee
+of the sequential numbering.
 .TP
 .B CPU
 The logical CPU number of a CPU as used by the Linux kernel.
index 992726c4520b90ec6a028bf25644d3bd63d32d3c..8f14b3af2818c1ed2928aea989071b02fb9eef81 100644 (file)
@@ -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:"),