From 855bab2a2ecd9c2be7c483501857580311d300de Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 9 Apr 2020 10:32:11 +0200 Subject: [PATCH] lscpu: add lscpu_cpu to internal API Signed-off-by: Karel Zak --- sys-utils/Makemodule.am | 1 + sys-utils/lscpu-api.h | 25 +++++++-- sys-utils/lscpu-cpu.c | 51 +++++++++++++++++ sys-utils/lscpu-cputype.c | 112 ++++++++++++++++++++++++++------------ 4 files changed, 149 insertions(+), 40 deletions(-) create mode 100644 sys-utils/lscpu-cpu.c diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am index 36b2a5b579..97d91e3f62 100644 --- a/sys-utils/Makemodule.am +++ b/sys-utils/Makemodule.am @@ -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 diff --git a/sys-utils/lscpu-api.h b/sys-utils/lscpu-api.h index a82dd4b433..c1e3372e8f 100644 --- a/sys-utils/lscpu-api.h +++ b/sys-utils/lscpu-api.h @@ -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 index 0000000000..1ef017a305 --- /dev/null +++ b/sys-utils/lscpu-cpu.c @@ -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; +} diff --git a/sys-utils/lscpu-cputype.c b/sys-utils/lscpu-cputype.c index c7d765767e..095fe1a2cc 100644 --- a/sys-utils/lscpu-cputype.c +++ b/sys-utils/lscpu-cputype.c @@ -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 */ -- 2.47.3