]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: add lscpu_read_cpulists()
authorKarel Zak <kzak@redhat.com>
Thu, 7 May 2020 12:47:24 +0000 (14:47 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 13 Nov 2020 08:19:02 +0000 (09:19 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/lscpu-api.h
sys-utils/lscpu-cputype.c

index ca4550c924148a6ee7e714209f49feaa68c099ef..30b324cbea4f6ae368cf696e4540b2c11474d011 100644 (file)
@@ -86,7 +86,8 @@ struct lscpu_arch {
 };
 
 struct lscpu_cxt {
-       const char *prefix;      /* path to /sys and /proc snapshot or NULL */
+       int maxcpus;            /* size in bits of kernel cpu mask */
+       const char *prefix;     /* path to /sys and /proc snapshot or NULL */
 
        struct path_cxt *syscpu; /* _PATH_SYS_CPU path handler */
        struct path_cxt *procfs; /* /proc path handler */
@@ -97,6 +98,23 @@ struct lscpu_cxt {
        size_t ncpus;
        struct lscpu_cpu **cpus;
 
+       /*
+        * 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.
+        */
+       size_t ncpuspos;        /* maximal possible CPUs */
+       int *idx2cpunum;        /* mapping index to CPU num */
+
+       size_t npresents;
+       cpu_set_t *present;     /* mask with present CPUs */
+
+       size_t nonlines;        /* aka number of trhreads */
+       cpu_set_t *online;      /* mask with online CPUs */
+
        struct lscpu_arch *arch;
 
        unsigned int noalive;
@@ -110,6 +128,7 @@ struct lscpu_cputype *lscpu_cputype_get_default(struct lscpu_cxt *cxt);
 
 int lscpu_read_cpuinfo(struct lscpu_cxt *cxt);
 int lscpu_read_architecture(struct lscpu_cxt *cxt);
+int lscpu_read_cpulists(struct lscpu_cxt *cxt);
 
 struct lscpu_cpu *lscpu_new_cpu(void);
 void lscpu_ref_cpu(struct lscpu_cpu *cpu);
index a4b1d811c5c32c506fb3aed01fa00c00ee73a5c7..a829007d3ee2abaf78101c77806280c7a9ef0abc 100644 (file)
@@ -436,6 +436,59 @@ int lscpu_read_architecture(struct lscpu_cxt *cxt)
        return 0;
 }
 
+int lscpu_read_cpulists(struct lscpu_cxt *cxt)
+{
+       size_t maxn;
+       size_t setsize;
+       cpu_set_t *cpuset = NULL;
+
+       assert(cxt);
+       DBG(GATHER, ul_debugobj(cxt, "reading cpulists"));
+
+       if (ul_path_read_s32(cxt->syscpu, &cxt->maxcpus, "kernel_max") == 0)
+               /* note that kernel_max is maximum index [NR_CPUS-1] */
+               cxt->maxcpus += 1;
+
+       else if (!cxt->noalive)
+               /* the root is '/' so we are working with data from the current kernel */
+               cxt->maxcpus = get_max_number_of_cpus();
+
+       if (cxt->maxcpus <= 0)
+               /* error or we are reading some /sys snapshot instead of the
+                * real /sys, let's use any crazy number... */
+               cxt->maxcpus = 2048;
+
+       maxn = cxt->maxcpus;
+       setsize = CPU_ALLOC_SIZE(maxn);
+
+       if (ul_path_readf_cpulist(cxt->syscpu, &cpuset, maxn, "possible") == 0) {
+               size_t num, idx;
+
+               cxt->ncpuspos = CPU_COUNT_S(setsize, cpuset);
+               cxt->idx2cpunum = xcalloc(cxt->ncpuspos, sizeof(int));
+
+               for (num = 0, idx = 0; num < maxn; num++) {
+                       if (CPU_ISSET_S(num, setsize, cpuset))
+                               cxt->idx2cpunum[idx++] = num;
+               }
+               cpuset_free(cpuset);
+               cpuset = NULL;
+       } else
+               err(EXIT_FAILURE, _("failed to determine number of CPUs: %s"),
+                               _PATH_SYS_CPU "/possible");
+
+
+       /* get mask for present CPUs */
+       if (ul_path_readf_cpulist(cxt->syscpu, &cxt->present, maxn, "present") == 0)
+               cxt->npresents = CPU_COUNT_S(setsize, cxt->present);
+
+       /* get mask for online CPUs */
+       if (ul_path_readf_cpulist(cxt->syscpu, &cxt->online, maxn, "online") == 0)
+               cxt->nonlines = CPU_COUNT_S(setsize, cxt->online);
+
+       return 0;
+}
+
 #ifdef TEST_PROGRAM_CPUTYPE
 /* TODO: move to lscpu.c */
 struct lscpu_cxt *lscpu_new_context(void)
@@ -464,6 +517,12 @@ void lscpu_free_context(struct lscpu_cxt *cxt)
        for (i = 0; i < cxt->ncputypes; i++)
                lscpu_unref_cputype(cxt->cputypes[i]);
 
+       free(cxt->idx2cpunum);
+       free(cxt->present);
+       free(cxt->online);
+       if (cxt->arch)
+               free(cxt->arch->name);
+       free(cxt->arch);
        free(cxt->cputypes);
        free(cxt->cpus);
        free(cxt);
@@ -485,6 +544,7 @@ int main(int argc, char **argv)
 
        lscpu_read_cpuinfo(cxt);
        lscpu_read_architecture(cxt);
+       lscpu_read_cpulists(cxt);
 
        lscpu_free_context(cxt);
        return EXIT_SUCCESS;