]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: cleanup -e
authorKarel Zak <kzak@redhat.com>
Fri, 30 Oct 2020 09:12:14 +0000 (10:12 +0100)
committerKarel Zak <kzak@redhat.com>
Fri, 13 Nov 2020 08:19:02 +0000 (09:19 +0100)
* keep one sharedmap per cache instance
* initialize topology IDs to -1
* rewrite -e code to use a new data structs

Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/lscpu-cpu.c
sys-utils/lscpu-cputype.c
sys-utils/lscpu-topology.c
sys-utils/lscpu.c
sys-utils/lscpu.h

index 7d96fa6a6e78389a0b923c71dc7b1a20bc4ebe01..f2159bd038918ca11211f439f180909ed543dc6e 100644 (file)
@@ -7,6 +7,12 @@ struct lscpu_cpu *lscpu_new_cpu(int id)
        cpu = xcalloc(1, sizeof(struct lscpu_cpu));
        cpu->refcount = 1;
        cpu->logical_id = id;
+       cpu->coreid = -1;
+       cpu->socketid = -1;
+       cpu->bookid = -1;
+       cpu->bookid = -1;
+       cpu->address = -1;
+       cpu->configured = -1;
 
        DBG(CPU, ul_debugobj(cpu, "alloc"));
        return cpu;
index e3459170dffaef3df55a410ce2148942309d83fa..86049b6a177d32ae6f5acf046405ea5623652d72 100644 (file)
@@ -511,6 +511,9 @@ int lscpu_read_cpuinfo(struct lscpu_cxt *cxt)
 
        DBG(GATHER, fprintf_cputypes(stderr, cxt));
 
+       if (pr->curr_cpu && !pr->curr_cpu->type)
+               lscpu_cpu_set_type(pr->curr_cpu, pr->curr_type);
+
        lscpu_unref_cputype(pr->curr_type);
        lscpu_unref_cpu(pr->curr_cpu);
 
index 8f948b48ceaa0c407f27f3236574800db1c35dfd..a33cbddc39800d5c26b1c6f34dd61773f8706024 100644 (file)
@@ -68,8 +68,7 @@ void lscpu_free_caches(struct lscpu_cache *caches, size_t n)
                free(c->type);
                free(c->allocation_policy);
                free(c->write_policy);
-
-               free_cpuset_array(c->sharedmaps, c->nsharedmaps);
+               free(c->sharedmap);
        }
        free(caches);
 }
@@ -233,6 +232,22 @@ size_t lscpu_get_cache_full_size(struct lscpu_cxt *cxt, const char *name)
        return sz;
 }
 
+struct lscpu_cache *lscpu_cpu_get_cache(struct lscpu_cxt *cxt,
+                               struct lscpu_cpu *cpu, const char *name)
+{
+       size_t i;
+
+       for (i = 0; i < cxt->ncaches; i++) {
+               struct lscpu_cache *ca = &cxt->caches[i];
+
+               if (strcmp(ca->name, name) == 0 &&
+                   CPU_ISSET_S(cpu->logical_id, cxt->setsize, ca->sharedmap))
+                       return ca;
+       }
+
+       return NULL;
+}
+
 /*
  * The cache is identifued by type+level+id.
  */
@@ -286,7 +301,6 @@ static int read_caches(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
 
        for (i = 0; i < ncaches; i++) {
                struct lscpu_cache *ca;
-               cpu_set_t *map;
                int id, level;
 
                if (ul_path_readf_s32(sys, &id, "cpu%d/cache/index%zu/id", num, i) != 0)
@@ -340,14 +354,10 @@ static int read_caches(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
                                ca->size = 0;
                }
 
-               /* information about how CPUs share different caches */
-               ul_path_readf_cpuset(sys, &map, cxt->maxcpus,
-                                 "cpu%d/cache/index%zu/shared_cpu_map", num, i);
-
-               if (!ca->sharedmaps)
-                       ca->sharedmaps = xcalloc(cxt->npossibles, sizeof(cpu_set_t *));
-
-               add_cpuset_to_array(ca->sharedmaps, &ca->nsharedmaps, map, cxt->setsize);
+               if (!ca->sharedmap)
+                       /* information about how CPUs share different caches */
+                       ul_path_readf_cpuset(sys, &ca->sharedmap, cxt->maxcpus,
+                                         "cpu%d/cache/index%zu/shared_cpu_map", num, i);
        }
 
        return 0;
@@ -399,6 +409,8 @@ static int read_polarization(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
        else
                cpu->polarization = POLAR_UNKNOWN;
 
+       if (cpu->type)
+               cpu->type->has_polarization = 1;
        return 0;
 }
 
@@ -411,6 +423,8 @@ static int read_address(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
                return 0;
 
        ul_path_readf_s32(sys, &cpu->address, "cpu%d/address", num);
+       if (cpu->type)
+               cpu->type->has_addresses = 1;
        return 0;
 }
 
@@ -423,6 +437,8 @@ static int read_configure(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
                return 0;
 
        ul_path_readf_s32(sys, &cpu->configured, "cpu%d/configure", num);
+       if (cpu->type)
+               cpu->type->has_configured = 1;
        return 0;
 }
 
index 9ab7aa159a8532609b4469bf346a5ee0c9d9d20a..0ed1f00bef50f12f72c0da494fe0a27b556401f4 100644 (file)
@@ -278,101 +278,94 @@ static void lscpu_free_context(struct lscpu_cxt *cxt)
        free(cxt);
 }
 
-#ifdef LSCPU_OLD_OUTPUT_CODE   /* temporary disabled for revrite */
+static void __fill_id( struct lscpu_cxt *cxt,
+                       struct lscpu_cpu *cpu,
+                       int id, cpu_set_t **map,
+                       size_t nitems,
+                       char *buf, size_t bufsz)
+{
+       *buf = '\0';
+
+       if (cxt->show_physical) {
+               if (id < 0)
+                       snprintf(buf, bufsz, "-");
+               else
+                       snprintf(buf, bufsz, "%d", id);
+       } else if (map) {
+               size_t i;
+
+               if (cpuset_ary_isset(cpu->logical_id, map, nitems,
+                                       cxt->setsize, &i) == 0)
+                       snprintf(buf, bufsz, "%zu", i);
+       }
+}
 
-static char *
-get_cell_data(struct lscpu_desc *desc, int idx, int col,
-             struct lscpu_modifier *mod,
-             char *buf, size_t bufsz)
+#define fill_id(_cxt, _cpu, NAME, _buf, _bufsz) \
+               __fill_id(_cxt, (_cpu), \
+                       (_cpu)-> NAME ## id, \
+                       (_cpu)->type-> NAME ## maps, \
+                       (_cpu)->type->n ## NAME ## s, \
+                       _buf, _bufsz)
+
+static char *get_cell_data(
+                       struct lscpu_cxt *cxt,
+                       struct lscpu_cpu *cpu, int col,
+                       char *buf, size_t bufsz)
 {
-       size_t setsize = CPU_ALLOC_SIZE(maxcpus);
        size_t i;
-       int cpu = real_cpu_num(desc, idx);
 
        *buf = '\0';
 
+       if (!cpu->type)
+               return NULL;
+
        switch (col) {
        case COL_CPU_CPU:
-               snprintf(buf, bufsz, "%d", cpu);
+               snprintf(buf, bufsz, "%d", cpu->logical_id);
                break;
        case COL_CPU_CORE:
-               if (mod->physical) {
-                       if (desc->coreids[idx] == -1)
-                               snprintf(buf, bufsz, "-");
-                       else
-                               snprintf(buf, bufsz, "%d", desc->coreids[idx]);
-               } else {
-                       if (cpuset_ary_isset(cpu, desc->coremaps,
-                                            desc->ncores, setsize, &i) == 0)
-                               snprintf(buf, bufsz, "%zu", i);
-               }
+               fill_id(cxt, cpu, core, buf, bufsz);
                break;
        case COL_CPU_SOCKET:
-               if (mod->physical) {
-                       if (desc->socketids[idx] ==  -1)
-                               snprintf(buf, bufsz, "-");
-                       else
-                               snprintf(buf, bufsz, "%d", desc->socketids[idx]);
-               } else {
-                       if (cpuset_ary_isset(cpu, desc->socketmaps,
-                                            desc->nsockets, setsize, &i) == 0)
-                               snprintf(buf, bufsz, "%zu", i);
-               }
-               break;
-       case COL_CPU_NODE:
-               if (cpuset_ary_isset(cpu, desc->nodemaps,
-                                    desc->nnodes, setsize, &i) == 0)
-                       snprintf(buf, bufsz, "%d", desc->idx2nodenum[i]);
+               fill_id(cxt, cpu, socket, buf, bufsz);
                break;
        case COL_CPU_DRAWER:
-               if (!desc->drawerids || !desc->drawermaps)
-                       break;
-               if (mod->physical) {
-                       if (desc->drawerids[idx] == -1)
-                               snprintf(buf, bufsz, "-");
-                       else
-                               snprintf(buf, bufsz, "%d", desc->drawerids[idx]);
-               } else {
-                       if (cpuset_ary_isset(cpu, desc->drawermaps,
-                                            desc->ndrawers, setsize, &i) == 0)
-                               snprintf(buf, bufsz, "%zu", i);
-               }
+               fill_id(cxt, cpu, drawer, buf, bufsz);
                break;
        case COL_CPU_BOOK:
-               if (!desc->bookids || !desc->bookmaps)
-                       break;
-               if (mod->physical) {
-                       if (desc->bookids[idx] == -1)
-                               snprintf(buf, bufsz, "-");
-                       else
-                               snprintf(buf, bufsz, "%d", desc->bookids[idx]);
-               } else {
-                       if (cpuset_ary_isset(cpu, desc->bookmaps,
-                                            desc->nbooks, setsize, &i) == 0)
-                               snprintf(buf, bufsz, "%zu", i);
-               }
+               fill_id(cxt, cpu, book, buf, bufsz);
+               break;
+       case COL_CPU_NODE:
+               if (cpuset_ary_isset(cpu->logical_id, cxt->nodemaps,
+                                    cxt->nnodes, cxt->setsize, &i) == 0)
+                       snprintf(buf, bufsz, "%d", cxt->idx2nodenum[i]);
                break;
        case COL_CPU_CACHE:
        {
+               const char *last = NULL;
                char *p = buf;
                size_t sz = bufsz;
-               int j;
 
-               for (j = desc->ncaches - 1; j >= 0; j--) {
-                       struct cpu_cache *ca = &desc->caches[j];
+               for (i = 0; i < cxt->ncaches; i++) {
+                       int x;
+                       struct lscpu_cache *ca;
+                       const char *name = cxt->caches[i].name;
 
-                       if (cpuset_ary_isset(cpu, ca->sharedmaps,
-                                            ca->nsharedmaps, setsize, &i) == 0) {
-                               int x = snprintf(p, sz, "%zu", i);
-                               if (x < 0 || (size_t) x >= sz)
-                                       return NULL;
-                               p += x;
-                               sz -= x;
-                       }
-                       if (j != 0) {
+                       if (last && strcmp(last, name) == 0)
+                               continue;
+                       last = name;
+                       ca = lscpu_cpu_get_cache(cxt, cpu, name);
+                       if (!ca)
+                               continue;
+                       x = snprintf(p, sz, "%d", ca->id);
+                       if (x < 0 || (size_t) x >= sz)
+                               return NULL;
+                       p += x;
+                       sz -= x;
+                       if (i + 1 < cxt->ncaches) {
                                if (sz < 2)
                                        return NULL;
-                               *p++ = mod->compat ? ',' : ':';
+                               *p++ = cxt->show_compatible ? ',' : ':';
                                *p = '\0';
                                sz--;
                        }
@@ -380,85 +373,90 @@ get_cell_data(struct lscpu_desc *desc, int idx, int col,
                break;
        }
        case COL_CPU_POLARIZATION:
-               if (desc->polarization) {
-                       int x = desc->polarization[idx];
-
-                       snprintf(buf, bufsz, "%s",
-                                mod->mode == LSCPU_OUTPUT_PARSABLE ?
-                                               polar_modes[x].parsable :
-                                               polar_modes[x].readable);
-               }
+               if (cpu->polarization < 0)
+                       break;
+               snprintf(buf, bufsz, "%s",
+                               cxt->mode == LSCPU_OUTPUT_PARSABLE ?
+                               polar_modes[cpu->polarization].parsable :
+                               polar_modes[cpu->polarization].readable);
                break;
        case COL_CPU_ADDRESS:
-               if (desc->addresses)
-                       snprintf(buf, bufsz, "%d", desc->addresses[idx]);
+               if (cpu->address < 0)
+                       break;
+               snprintf(buf, bufsz, "%d", cpu->address);
                break;
        case COL_CPU_CONFIGURED:
-               if (!desc->configured)
+               if (cpu->configured < 0)
                        break;
-               if (mod->mode == LSCPU_OUTPUT_PARSABLE)
+               if (cxt->mode == LSCPU_OUTPUT_PARSABLE)
                        snprintf(buf, bufsz, "%s",
-                                desc->configured[idx] ? _("Y") : _("N"));
+                                cpu->configured ? _("Y") : _("N"));
                else
                        snprintf(buf, bufsz, "%s",
-                                desc->configured[idx] ? _("yes") : _("no"));
+                                cpu->configured ? _("yes") : _("no"));
                break;
        case COL_CPU_ONLINE:
-               if (!desc->online)
+               if (!cxt->online)
                        break;
-               if (mod->mode == LSCPU_OUTPUT_PARSABLE)
+               if (cxt->mode == LSCPU_OUTPUT_PARSABLE)
                        snprintf(buf, bufsz, "%s",
-                                is_cpu_online(desc, cpu) ? _("Y") : _("N"));
+                                is_cpu_online(cxt, cpu) ? _("Y") : _("N"));
                else
                        snprintf(buf, bufsz, "%s",
-                                is_cpu_online(desc, cpu) ? _("yes") : _("no"));
+                                is_cpu_online(cxt, cpu) ? _("yes") : _("no"));
                break;
        case COL_CPU_MAXMHZ:
-               if (desc->maxmhz && desc->maxmhz[idx])
-                       xstrncpy(buf, desc->maxmhz[idx], bufsz);
+               if (cpu->mhz_max_freq)
+                       snprintf(buf, bufsz, "%.4f", cpu->mhz_max_freq);
                break;
        case COL_CPU_MINMHZ:
-               if (desc->minmhz && desc->minmhz[idx])
-                       xstrncpy(buf, desc->minmhz[idx], bufsz);
+               if (cpu->mhz_min_freq)
+                       snprintf(buf, bufsz, "%.4f", cpu->mhz_min_freq);
                break;
        }
        return buf;
 }
 
-static char *
-get_cell_header(struct lscpu_desc *desc, int col,
-               struct lscpu_modifier *mod,
-               char *buf, size_t bufsz)
+static char *get_cell_header(
+                       struct lscpu_cxt *cxt, int col,
+                       char *buf, size_t bufsz)
 {
        *buf = '\0';
 
        if (col == COL_CPU_CACHE) {
+               const char *last = NULL;
                char *p = buf;
                size_t sz = bufsz;
-               int i;
+               size_t i;
+
+               for (i = 0; i < cxt->ncaches; i++) {
+                       struct lscpu_cache *ca = &cxt->caches[i];
+                       int x;
+
+                       if (last && strcmp(last, ca->name) == 0)
+                               continue;
+                       last = ca->name;
 
-               for (i = desc->ncaches - 1; i >= 0; i--) {
-                       int x = snprintf(p, sz, "%s", desc->caches[i].name);
+                       x = snprintf(p, sz, "%s", ca->name);
                        if (x < 0 || (size_t) x >= sz)
                                return NULL;
                        sz -= x;
                        p += x;
-                       if (i > 0) {
+                       if (i + 1 < cxt->ncaches) {
                                if (sz < 2)
                                        return NULL;
-                               *p++ = mod->compat ? ',' : ':';
+                               *p++ = cxt->show_compatible ? ',' : ':';
                                *p = '\0';
                                sz--;
                        }
                }
-               if (desc->ncaches)
+               if (cxt->ncaches)
                        return buf;
        }
        snprintf(buf, bufsz, "%s", coldescs_cpu[col].name);
        return buf;
 }
 
-#endif
 
 static void caches_add_line(struct lscpu_cxt *cxt,
                            struct libscols_table *tb,
@@ -694,69 +692,66 @@ print_cpus_parsable(struct lscpu_desc *desc, int cols[], int ncols,
                putchar('\n');
        }
 }
+#endif
 
 /*
  * [-e] backend
  */
-static void
-print_cpus_readable(struct lscpu_desc *desc, int cols[], int ncols,
-              struct lscpu_modifier *mod)
+static void print_cpus_readable(struct lscpu_cxt *cxt, int cols[], size_t ncols)
 {
-       int i;
+       size_t i;
        char buf[BUFSIZ];
        const char *data;
-       struct libscols_table *table;
+       struct libscols_table *tb;
 
        scols_init_debug(0);
 
-       table = scols_new_table();
-       if (!table)
+       tb = scols_new_table();
+       if (!tb)
                 err(EXIT_FAILURE, _("failed to allocate output table"));
-       if (mod->json) {
-               scols_table_enable_json(table, 1);
-               scols_table_set_name(table, "cpus");
+       if (cxt->json) {
+               scols_table_enable_json(tb, 1);
+               scols_table_set_name(tb, "cpus");
        }
 
        for (i = 0; i < ncols; i++) {
-               data = get_cell_header(desc, cols[i], mod, buf, sizeof(buf));
-               if (!scols_table_new_column(table, data, 0, coldescs_cpu[cols[i]].flags))
+               data = get_cell_header(cxt, cols[i], buf, sizeof(buf));
+               if (!scols_table_new_column(tb, data, 0, coldescs_cpu[cols[i]].flags))
                        err(EXIT_FAILURE, _("failed to allocate output column"));
        }
 
-       for (i = 0; i < desc->ncpuspos; i++) {
-               int c;
-               struct libscols_line *line;
-               int cpu = real_cpu_num(desc, i);
+       for (i = 0; i < cxt->npossibles; i++) {
+               size_t c;
+               struct libscols_line *ln;
+               struct lscpu_cpu *cpu = cxt->cpus[i];
 
-               if (desc->online) {
-                       if (!mod->offline && !is_cpu_online(desc, cpu))
+               if (cxt->online) {
+                       if (!cxt->show_offline && !is_cpu_online(cxt, cpu))
                                continue;
-                       if (!mod->online && is_cpu_online(desc, cpu))
+                       if (!cxt->show_online && is_cpu_online(cxt, cpu))
                                continue;
                }
-               if (desc->present && !is_cpu_present(desc, cpu))
+
+               if (cxt->present && !is_cpu_present(cxt, cpu))
                        continue;
 
-               line = scols_table_new_line(table, NULL);
-               if (!line)
+               ln = scols_table_new_line(tb, NULL);
+               if (!ln)
                        err(EXIT_FAILURE, _("failed to allocate output line"));
 
                for (c = 0; c < ncols; c++) {
-                       data = get_cell_data(desc, i, cols[c], mod,
-                                            buf, sizeof(buf));
+                       data = get_cell_data(cxt, cpu, cols[c], buf, sizeof(buf));
                        if (!data || !*data)
                                data = "-";
-                       if (scols_line_set_data(line, c, data))
+                       if (scols_line_set_data(ln, c, data))
                                err(EXIT_FAILURE, _("failed to add output data"));
                }
        }
 
-       scols_print_table(table);
-       scols_unref_table(table);
+       scols_print_table(tb);
+       scols_unref_table(tb);
 }
 
-#endif
-
 static struct libscols_line *
        __attribute__ ((__format__(printf, 4, 5)))
        add_summary_sprint(struct libscols_table *tb,
@@ -1310,50 +1305,52 @@ int main(int argc, char *argv[])
                }
                print_caches_readable(cxt, columns, ncolumns);
                break;
-       }
-
-#ifdef LSCPU_OLD_OUTPUT_CODE
-       case LSCPU_OUTPUT_PARSABLE:
-               if (!ncolumns) {
-                       columns[ncolumns++] = COL_CPU_CPU;
-                       columns[ncolumns++] = COL_CPU_CORE;
-                       columns[ncolumns++] = COL_CPU_SOCKET;
-                       columns[ncolumns++] = COL_CPU_NODE;
-                       columns[ncolumns++] = COL_CPU_CACHE;
-                       mod->compat = 1;
-               }
-               print_cpus_parsable(desc, columns, ncolumns, mod);
-               break;
        case LSCPU_OUTPUT_READABLE:
                if (!ncolumns) {
                        /* No list was given. Just print whatever is there. */
+                       struct lscpu_cputype *ct = lscpu_cputype_get_default(cxt);
+
                        columns[ncolumns++] = COL_CPU_CPU;
-                       if (desc->nodemaps)
+                       if (cxt->nnodes)
                                columns[ncolumns++] = COL_CPU_NODE;
-                       if (desc->drawermaps)
+                       if (ct && ct->ndrawers)
                                columns[ncolumns++] = COL_CPU_DRAWER;
-                       if (desc->bookmaps)
+                       if (ct && ct->nbooks)
                                columns[ncolumns++] = COL_CPU_BOOK;
-                       if (desc->socketmaps)
+                       if (ct && ct->nsockets)
                                columns[ncolumns++] = COL_CPU_SOCKET;
-                       if (desc->coremaps)
+                       if (ct && ct->ncores)
                                columns[ncolumns++] = COL_CPU_CORE;
-                       if (desc->caches)
+                       if (cxt->ncaches)
                                columns[ncolumns++] = COL_CPU_CACHE;
-                       if (desc->online)
+                       if (cxt->online)
                                columns[ncolumns++] = COL_CPU_ONLINE;
-                       if (desc->configured)
+                       if (ct && ct->has_configured)
                                columns[ncolumns++] = COL_CPU_CONFIGURED;
-                       if (desc->polarization)
+                       if (ct && ct->has_polarization)
                                columns[ncolumns++] = COL_CPU_POLARIZATION;
-                       if (desc->addresses)
+                       if (ct && ct->has_addresses)
                                columns[ncolumns++] = COL_CPU_ADDRESS;
-                       if (desc->maxmhz)
+                       if (ct && ct->has_freq) {
                                columns[ncolumns++] = COL_CPU_MAXMHZ;
-                       if (desc->minmhz)
                                columns[ncolumns++] = COL_CPU_MINMHZ;
+                       }
                }
-               print_cpus_readable(desc, columns, ncolumns, mod);
+               print_cpus_readable(cxt, columns, ncolumns);
+               break;
+       }
+
+#ifdef LSCPU_OLD_OUTPUT_CODE
+       case LSCPU_OUTPUT_PARSABLE:
+               if (!ncolumns) {
+                       columns[ncolumns++] = COL_CPU_CPU;
+                       columns[ncolumns++] = COL_CPU_CORE;
+                       columns[ncolumns++] = COL_CPU_SOCKET;
+                       columns[ncolumns++] = COL_CPU_NODE;
+                       columns[ncolumns++] = COL_CPU_CACHE;
+                       mod->compat = 1;
+               }
+               print_cpus_parsable(desc, columns, ncolumns, mod);
                break;
        }
 
index 78948c4b6ad7d8df301fd1242e67a770688c7260..935734ce7ff972bdb049ef21f02e84eb5c40a24a 100644 (file)
@@ -51,7 +51,7 @@ struct lscpu_cache {
        unsigned int    coherency_line_size;
 
        size_t          nsharedmaps;
-       cpu_set_t       **sharedmaps;
+       cpu_set_t       *sharedmap;
 };
 
 struct lscpu_cputype {
@@ -94,7 +94,10 @@ struct lscpu_cputype {
        size_t          ndrawers;
        cpu_set_t       **drawermaps;
 
-       unsigned int    has_freq : 1;           /* has max/nim frequence info */
+       unsigned int    has_freq : 1,
+                       has_configured : 1,
+                       has_polarization : 1,
+                       has_addresses : 1;
 };
 
 /* dispatching modes */
@@ -231,6 +234,7 @@ struct lscpu_cxt {
                     show_online : 1,
                     show_offline : 1,
                     show_physical : 1,
+                    show_compatible : 1,
                     hex : 1,
                     json : 1,
                     bytes : 1;
@@ -260,14 +264,16 @@ int lscpu_read_numas(struct lscpu_cxt *cxt);
 void lscpu_free_caches(struct lscpu_cache *caches, size_t n);
 void lscpu_sort_caches(struct lscpu_cache *caches, size_t n);
 
+size_t lscpu_get_cache_full_size(struct lscpu_cxt *cxt, const char *name);
+struct lscpu_cache *lscpu_cpu_get_cache(struct lscpu_cxt *cxt,
+                                struct lscpu_cpu *cpu, const char *name);
+
 int lscpu_read_topology(struct lscpu_cxt *cxt);
 void lscpu_cputype_free_topology(struct lscpu_cputype *ct);
 
 float lsblk_cputype_get_maxmhz(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
 float lsblk_cputype_get_minmhz(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
 
-size_t lscpu_get_cache_full_size(struct lscpu_cxt *cxt, const char *name);
-
 struct lscpu_arch *lscpu_read_architecture(struct lscpu_cxt *cxt);
 void lscpu_free_architecture(struct lscpu_arch *ar);