]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: add lscpu_cpu to internal API
authorKarel Zak <kzak@redhat.com>
Thu, 9 Apr 2020 08:32:11 +0000 (10:32 +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/Makemodule.am
sys-utils/lscpu-api.h
sys-utils/lscpu-cpu.c [new file with mode: 0644]
sys-utils/lscpu-cputype.c

index 36b2a5b579923971a3729a46c6ee3b7237662e94..97d91e3f625e622b1f0ff5dc9ee376226216cc45 100644 (file)
@@ -401,6 +401,7 @@ dist_man_MANS += sys-utils/lscpu.1
 
 check_PROGRAMS += test_cputype
 test_cputype_SOURCES = sys-utils/lscpu-cputype.c \
+                      sys-utils/lscpu-cpu.c \
                       sys-utils/lscpu-api.h
 test_cputype_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_CPUTYPE
 test_cputype_LDADD = $(LDADD) libcommon.la
index a82dd4b4330282e2096291410c9154cbcbaccaad..c1e3372e8f15de8e4cd95e7041a9a734a925091a 100644 (file)
@@ -16,6 +16,7 @@
 #define LSCPU_DEBUG_MISC       (1 << 2)
 #define LSCPU_DEBUG_GATHER     (1 << 3)
 #define LSCPU_DEBUG_TYPE       (1 << 4)
+#define LSCPU_DEBUG_CPU                (1 << 5)
 #define LSBLK_DEBUG_ALL                0xFFFF
 
 UL_DEBUG_DECLARE_MASK(lscpu);
@@ -31,8 +32,6 @@ UL_DEBUG_DECLARE_MASK(lscpu);
 #define _PATH_SYS_NODE         _PATH_SYS_SYSTEM "/node"
 
 struct lscpu_cputype {
-       cpu_set_t       *map;   /* which cpus use this type */
-
        int     refcount;
 
        char    *arch;
@@ -49,8 +48,6 @@ struct lscpu_cputype {
        int     virtype;        /* VIRT_PARA|FULL|NONE ? */
        char    *stepping;
        char    *bogomips;
-       char    *dynamic_mhz;
-       char    *static_mhz;
        char    *flags;
        char    *mtid;          /* maximum thread id (s390) */
        char    *addrsz;        /* address sizes */
@@ -74,8 +71,14 @@ struct lscpu_cputype {
 };
 
 struct lscpu_cpu {
+       int refcount;
+       struct lscpu_cputype *type;
+
        int logical_id;
        char    *mhz;
+
+       char    *dynamic_mhz;
+       char    *static_mhz;
 };
 
 struct lscpu_cxt {
@@ -86,14 +89,26 @@ struct lscpu_cxt {
 
        size_t ncputypes;
        struct lscpu_cputype **cputypes;
+
+       size_t ncpus;
+       struct lscpu_cpu **cpus;
+
 };
 
 struct lscpu_cputype *lscpu_new_cputype(void);
 void lscpu_ref_cputype(struct lscpu_cputype *ct);
 void lscpu_unref_cputype(struct lscpu_cputype *ct);
+struct lscpu_cputype *lscpu_add_cputype(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
 int lscpu_read_cpuinfo(struct lscpu_cxt *cxt);
 
+struct lscpu_cpu *lscpu_new_cpu(void);
+void lscpu_ref_cpu(struct lscpu_cpu *cpu);
+void lscpu_unref_cpu(struct lscpu_cpu *cpu);
+int lscpu_add_cpu(struct lscpu_cxt *cxt,
+                  struct lscpu_cpu *cpu,
+                  struct lscpu_cputype *ct);
+
 struct lscpu_cxt *lscpu_new_context(void);
-static void lscpu_free_context(struct lscpu_cxt *cxt);
+void lscpu_free_context(struct lscpu_cxt *cxt);
 
 #endif /* LSCPU_API_H */
diff --git a/sys-utils/lscpu-cpu.c b/sys-utils/lscpu-cpu.c
new file mode 100644 (file)
index 0000000..1ef017a
--- /dev/null
@@ -0,0 +1,51 @@
+#include "lscpu-api.h"
+
+struct lscpu_cpu *lscpu_new_cpu(void)
+{
+       struct lscpu_cpu *cpu;
+
+       cpu = xcalloc(1, sizeof(struct lscpu_cpu));
+       cpu->refcount = 1;
+
+       DBG(CPU, ul_debugobj(cpu, "alloc"));
+       return cpu;
+}
+
+void lscpu_ref_cpu(struct lscpu_cpu *cpu)
+{
+       if (cpu)
+               cpu->refcount++;
+}
+
+void lscpu_unref_cpu(struct lscpu_cpu *cpu)
+{
+       if (!cpu)
+               return;
+
+       if (--cpu->refcount <= 0) {
+               DBG(CPU, ul_debugobj(cpu, "  freeing"));
+               lscpu_unref_cputype(cpu->type);
+               free(cpu);
+       }
+}
+
+int lscpu_add_cpu(struct lscpu_cxt *cxt,
+                 struct lscpu_cpu *cpu,
+                 struct lscpu_cputype *ct)
+{
+       struct lscpu_cputype *type;
+
+       type = lscpu_add_cputype(cxt, ct);
+
+       cxt->cpus = xrealloc(cxt->cpus, (cxt->ncpus + 1)
+                               * sizeof(struct lscpu_cpu *));
+
+       cxt->cpus[cxt->ncpus] = cpu;
+       cxt->ncpus++;
+       lscpu_ref_cpu(cpu);
+
+       cpu->type = type;
+       lscpu_ref_cputype(type);
+
+       return 0;
+}
index c7d765767e256a89f73a43e1c3a236641a0ba194..095fe1a2cc02f618de485facf56687e9f53e38b1 100644 (file)
@@ -53,11 +53,40 @@ void lscpu_unref_cputype(struct lscpu_cputype *ct)
                return;
 
        if (--ct->refcount <= 0) {
-               DBG(TYPE, ul_debugobj(ct, " freeing"));
+               DBG(TYPE, ul_debugobj(ct, "  freeing"));
                free(ct);
        }
 }
 
+
+#define match(astr, bstr) \
+               ((!astr && !bstr) || (astr && bstr && strcmp(astr, bstr) == 0))
+
+struct lscpu_cputype *lscpu_add_cputype(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
+{
+       size_t i;
+
+       /* ignore if already in the context */
+       for (i = 0; i < cxt->ncputypes; i++) {
+               struct lscpu_cputype *x = cxt->cputypes[i];
+
+               if (match(x->vendor, ct->vendor) &&
+                   match(x->model, ct->model) &&
+                   match(x->modelname, ct->modelname) &&
+                   match(x->cpu, ct->cpu) &&
+                   match(x->stepping, ct->stepping))
+                       return x;
+       }
+
+       /* add */
+       cxt->cputypes = xrealloc(cxt->cputypes, (cxt->ncputypes + 1)
+                               * sizeof(struct lscpu_cputype *));
+       cxt->cputypes[cxt->ncputypes] = ct;
+       cxt->ncputypes++;
+       lscpu_ref_cputype(ct);
+       return ct;
+}
+
 /* Describes /proc/cpuinfo fields */
 struct cpuinfo_pattern {
        int id;                 /* field ID */
@@ -111,8 +140,6 @@ static const struct cpuinfo_pattern type_patterns[] =
        DEF_PAT_CPUTYPE( "address sizes",       PAT_ADDRESS_SIZES,      addrsz),/* x86 */
        DEF_PAT_CPUTYPE( "bogomips",            PAT_BOGOMIPS,   bogomips),
        DEF_PAT_CPUTYPE( "bogomips per cpu",    PAT_BOGOMIPS,   bogomips),      /* s390 */
-       DEF_PAT_CPUTYPE( "cpu MHz dynamic",     PAT_MHZ_DYNAMIC,dynamic_mhz),   /* s390 */
-       DEF_PAT_CPUTYPE( "cpu MHz static",      PAT_MHZ_STATIC, static_mhz),    /* s390 */
        DEF_PAT_CPUTYPE( "cpu family",          PAT_FAMILY,     family),
        DEF_PAT_CPUTYPE( "cpu",                 PAT_CPU,        cpu),
        DEF_PAT_CPUTYPE( "family",              PAT_FAMILY,     family),
@@ -125,7 +152,7 @@ static const struct cpuinfo_pattern type_patterns[] =
        DEF_PAT_CPUTYPE( "stepping",            PAT_STEPPING,   stepping),
        DEF_PAT_CPUTYPE( "type",                PAT_TYPE,       flags),         /* sparc64 */
        DEF_PAT_CPUTYPE( "vendor",              PAT_VENDOR,     vendor),
-       DEF_PAT_CPUTYPE( "vendor_id",           PAT_VENDOR,     vendor),
+       DEF_PAT_CPUTYPE( "vendor_id",           PAT_VENDOR,     vendor),        /* s390 */
 };
 
 /*
@@ -141,6 +168,8 @@ static const struct cpuinfo_pattern type_patterns[] =
 static const struct cpuinfo_pattern cpu_patterns[] =
 {
        /* Sort by fields name! */
+       DEF_PAT_CPU( "cpu MHz dynamic", PAT_MHZ_DYNAMIC,dynamic_mhz),   /* s390 */
+       DEF_PAT_CPU( "cpu MHz static",  PAT_MHZ_STATIC, static_mhz),    /* s390 */
        DEF_PAT_CPU( "cpu MHz",         PAT_MHZ,        mhz),
         DEF_PAT_CPU( "processor",      PAT_PROCESSOR,  logical_id),
 };
@@ -227,22 +256,13 @@ static int cpuinfo_parse_line(    struct lscpu_cputype *ct,
        return 0;
 }
 
-static void print_cputype(struct lscpu_cputype *ct, FILE *f)
-{
-       fprintf(f, "vendor=\"%s\"\n", ct->vendor);
-       fprintf(f, "model=\"%s\"\n", ct->model);
-       fprintf(f, "flags=\"%s\"\n", ct->flags);
-}
-
-
-
-
 int lscpu_read_cpuinfo(struct lscpu_cxt *cxt)
 {
        struct lscpu_cputype *ct = NULL;
        struct lscpu_cpu *cpu = NULL;
        FILE *fp;
        char buf[BUFSIZ];
+       int nblocks = 0, keeptype = 0;
 
        DBG(GATHER, ul_debugobj(cxt, "reading cpuinfo"));
 
@@ -254,41 +274,59 @@ int lscpu_read_cpuinfo(struct lscpu_cxt *cxt)
                const char *p = skip_space(buf);
 
                if (*buf && !*p) {
-                       if (ct) {
-                               ON_DBG(GATHER, print_cputype(ct, stdout));
-                               //lscpu_add_cputype(&cxt->cputypes, &cxt->ncputypes, ct);
+                       /* empty line between data in /proc/cpuinfo */
+                       nblocks++;
+
+                       if (nblocks == 1) {
+                               /* For some architectures cpuinfo contains description
+                                * block before the list of CPUs (e.g. s390). The block
+                                * contains description for all CPUs, so we keep it as
+                                * one cputype.
+                                *
+                                * Note that for another architectures it's
+                                * fine to create cputype for each CPU, because
+                                * lscpu_add_cputype() and lscpu_add_cpu() are
+                                * able to deduplicate it if necessary.
+                                */
+                               if (ct->vendor && strncasecmp(ct->vendor, "IBM/", 4) == 0) {
+                                       lscpu_add_cputype(cxt, ct);
+                                       keeptype = 1;
+                                       continue;
+                               }
                        }
-                       lscpu_unref_cputype(ct);
-/*                     lscpu_unref_cpu(cpu);*/
-                       ct = NULL, cpu = NULL;
+
+                       if (ct && cpu)
+                               lscpu_add_cpu(cxt, cpu, ct);
+
+                       if (!keeptype) {
+                               lscpu_unref_cputype(ct);
+                               ct = NULL;
+                       }
+
+                       lscpu_unref_cpu(cpu);
+                       cpu = NULL;
                        continue;
                }
                if (!ct)
                        ct = lscpu_new_cputype();
-/*             if (!cpu)
-                       cpu = lscpu_new_cpu();*/
+               if (!cpu)
+                       cpu = lscpu_new_cpu();
 
                cpuinfo_parse_line(ct, cpu, p);
-
-               /* TODO: else lscpu_parse_cache(cxt, buf); */
        }
 
-       /*
-       if (ct)
-               lscpu_add_cputype(&cxt->cputypes, &cxt->ncputypes, ct);
-       if (cpu)
-               lscpu_add_cpu(&cxt->cputs, &cxt->ncpus, cpu);
-       */
+       if (cpu && ct)
+               lscpu_add_cpu(cxt, cpu, ct);
 
+       lscpu_unref_cpu(cpu);
        lscpu_unref_cputype(ct);
-       /*lscpu_unref_cpu(cpu);*/
        fclose(fp);
 
-       return 0;
+       DBG(GATHER, ul_debugobj(cxt, " parsed %d cpuinfo blocks", nblocks));
+
        return 0;
 }
 
-
 #ifdef TEST_PROGRAM_CPUTYPE
 /* TODO: move to lscpu.c */
 struct lscpu_cxt *lscpu_new_context(void)
@@ -296,7 +334,7 @@ struct lscpu_cxt *lscpu_new_context(void)
        return xcalloc(1, sizeof(struct lscpu_cxt));
 }
 
-static void lscpu_free_context(struct lscpu_cxt *cxt)
+void lscpu_free_context(struct lscpu_cxt *cxt)
 {
        size_t i;
 
@@ -309,11 +347,16 @@ static void lscpu_free_context(struct lscpu_cxt *cxt)
        ul_unref_path(cxt->syscpu);
        ul_unref_path(cxt->procfs);
 
+       DBG(MISC, ul_debugobj(cxt, " freeing cpus"));
+       for (i = 0; i < cxt->ncpus; i++)
+               lscpu_unref_cpu(cxt->cpus[i]);
+
        DBG(MISC, ul_debugobj(cxt, " freeing types"));
        for (i = 0; i < cxt->ncputypes; i++)
                lscpu_unref_cputype(cxt->cputypes[i]);
 
        free(cxt->cputypes);
+       free(cxt->cpus);
        free(cxt);
 }
 
@@ -332,7 +375,6 @@ int main(int argc, char **argv)
        lscpu_read_cpuinfo(cxt);
 
        lscpu_free_context(cxt);
-
        return EXIT_SUCCESS;
 }
 #endif /* TEST_PROGRAM_CPUTYPES */