size_t ncputypes;
struct lscpu_cputype **cputypes;
- /* CPUs as read from /proc/cpuinfo, it means online CPUs only */
- 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.
- *
- * TODO: Do we really need it if we have lscpu_cpu->logical_id?
- */
- size_t ncpuspos; /* maximal possible CPUs */
- int *idx2cpunum; /* mapping index to CPU num */
+ size_t npossibles; /* number of possible CPUs */
+ struct lscpu_cpu **cpus; /* possible CPUs, contains gaps (cups[n]=NULL) */
size_t npresents;
cpu_set_t *present; /* mask with present CPUs */
struct lscpu_virt *lscpu_read_virtualization(struct lscpu_cxt *cxt);
void lscpu_free_virtualization(struct lscpu_virt *virt);
-struct lscpu_cpu *lscpu_new_cpu(void);
+struct lscpu_cpu *lscpu_new_cpu(int id);
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_cpu *lscpu_get_cpu(struct lscpu_cxt *cxt, int logical_id);
+int lscpu_cpu_set_type(struct lscpu_cpu *cpu, struct lscpu_cputype *type);
+int lscpu_create_cpus(struct lscpu_cxt *cxt, cpu_set_t *cpuset, size_t setsize);
int lscpu_cpus_apply_type(struct lscpu_cxt *cxt, struct lscpu_cputype *type);
struct lscpu_cpu *lscpu_cpus_loopup_by_type(struct lscpu_cxt *cxt, struct lscpu_cputype *ct);
#include "lscpu-api.h"
-struct lscpu_cpu *lscpu_new_cpu(void)
+struct lscpu_cpu *lscpu_new_cpu(int id)
{
struct lscpu_cpu *cpu;
cpu = xcalloc(1, sizeof(struct lscpu_cpu));
cpu->refcount = 1;
- cpu->logical_id = -1;
+ cpu->logical_id = id;
DBG(CPU, ul_debugobj(cpu, "alloc"));
return cpu;
}
}
-int lscpu_add_cpu(struct lscpu_cxt *cxt,
- struct lscpu_cpu *cpu,
- struct lscpu_cputype *ct)
+/*
+ * Create and initialize array with CPU structs according to @cpuset.
+ */
+int lscpu_create_cpus(struct lscpu_cxt *cxt, cpu_set_t *cpuset, size_t setsize)
{
- struct lscpu_cputype *type;
+ size_t n;
- /* make sure the type exists */
- if (ct)
- type = lscpu_add_cputype(cxt, ct);
- else
- type = lscpu_cputype_get_default(cxt);
+ assert(!cxt->cpus);
- cxt->cpus = xrealloc(cxt->cpus, (cxt->ncpus + 1)
- * sizeof(struct lscpu_cpu *));
+ cxt->npossibles = CPU_COUNT_S(setsize, cpuset);
+ cxt->cpus = xcalloc(1, cxt->npossibles * sizeof(struct lscpu_cpu *));
- cxt->cpus[cxt->ncpus] = cpu;
- cxt->ncpus++;
- lscpu_ref_cpu(cpu);
+ for (n = 0; n < cxt->npossibles; n++) {
+ if (CPU_ISSET_S(n, setsize, cpuset))
+ cxt->cpus[n] = lscpu_new_cpu(n);
+ }
+
+ return 0;
+}
+
+int lscpu_cpu_set_type(struct lscpu_cpu *cpu, struct lscpu_cputype *type)
+{
+ struct lscpu_cputype *old = cpu->type;
+
+ cpu->type = type;
if (type) {
- cpu->type = type;
lscpu_ref_cputype(type);
type->ncpus++;
}
-
+ if (old) {
+ lscpu_unref_cputype(old);
+ old->ncpus--;
+ }
return 0;
}
{
size_t i;
- for (i = 0; i < cxt->ncpus; i++) {
+ for (i = 0; i < cxt->npossibles; i++) {
struct lscpu_cpu *cpu = cxt->cpus[i];
- if (!cpu->type) {
- cpu->type = type;
- lscpu_ref_cputype(type);
- type->ncpus++;
- }
+ if (cpu && !cpu->type)
+ lscpu_cpu_set_type(cpu, type);
}
return 0;
}
+
+struct lscpu_cpu *lscpu_get_cpu(struct lscpu_cxt *cxt, int logical_id)
+{
+ size_t i;
+
+ for (i = 0; i < cxt->npossibles; i++) {
+ struct lscpu_cpu *cpu = cxt->cpus[i];
+
+ if (cpu && cpu->logical_id == logical_id)
+ return cpu;
+ }
+
+ return NULL;
+}
*
* Note that s390-like "processor <n>:" lines are not suported here.
*/
-static int cpuinfo_parse_line( struct lscpu_cputype **ct,
+static int cpuinfo_parse_line( struct lscpu_cxt *cxt,
+ struct lscpu_cputype **ct,
struct lscpu_cpu **cpu,
const char *str)
{
rtrim_whitespace((unsigned char *)buf);
+ /* prepare value */
+ v = skip_space(v);
+ if (!v || !*v)
+ return -EINVAL;
+
/* search in cpu-types patterns */
key.pattern = buf;
pat = bsearch(&key, type_patterns,
sizeof(struct cpuinfo_pattern),
cmp_pattern);
if (pat) {
- /* CPU type */
if (!*ct)
*ct = lscpu_new_cputype();
stru = *ct;
+
+ /* search in cpu patterns */
} else {
- /* search in cpu patterns */
pat = bsearch(&key, cpu_patterns,
ARRAY_SIZE(cpu_patterns),
sizeof(struct cpuinfo_pattern),
cmp_pattern);
+
if (pat) {
- if (!*cpu)
- *cpu = lscpu_new_cpu();
+ if (pat->id == PAT_PROCESSOR) {
+ /* switch to another CPU only */
+ *cpu = lscpu_get_cpu(cxt, atoi(v));
+ return 0;
+ }
stru = *cpu;
}
}
return 1;
}
- /* prepare value */
- v = skip_space(v);
- if (!v || !*v)
- return -EINVAL;
-
- /* copy value to struct */
- switch (pat->id) {
- case PAT_PROCESSOR:
- (*cpu)->logical_id = atoi(v);
- break;
- default:
- /* set value as a string and cleanup */
- strdup_to_offset(stru, pat->offset, v);
- data = (char **) ((char *) stru + pat->offset);
- rtrim_whitespace((unsigned char *) *data);
- break;
- }
+ /* set value as a string and cleanup */
+ strdup_to_offset(stru, pat->offset, v);
+ data = (char **) ((char *) stru + pat->offset);
+ rtrim_whitespace((unsigned char *) *data);
return 0;
}
/*
* s390-like "processor <n>: value = xxx, value = yyy" lines parser.
*/
-static int cpuinfo_parse_processor_line(struct lscpu_cpu **cpu, const char *str)
+static int cpuinfo_parse_processor_line(struct lscpu_cxt *cxt, struct lscpu_cpu **cpu, const char *str)
{
const char *v;
char *end = NULL;
if (errno || !end || v == end || *end != ':')
return -EINVAL;
- if (!*cpu)
- *cpu = lscpu_new_cpu();
+ /* switch to another CPU */
+ *cpu = lscpu_get_cpu(cxt, n);
- (*cpu)->logical_id = n;
+ /* we don't parse anythign more from the line */
return 0;
}
FILE *fp;
char buf[BUFSIZ];
+ assert(cxt->npossibles); /* lscpu_create_cpus() required */
+ assert(cxt->cpus);
+
DBG(GATHER, ul_debugobj(cxt, "reading cpuinfo"));
fp = ul_path_fopen(cxt->procfs, "r", "cpuinfo");
* Blank line separates CPUs
*/
if (cpu)
- lscpu_add_cpu(cxt, cpu, type);
+ lscpu_cpu_set_type(cpu, type);
else if (type) {
/* Generic non-cpu data. For some architectures
* cpuinfo contains description block (at the
lscpu_add_cputype(cxt, type);
}
- lscpu_unref_cpu(cpu);
lscpu_unref_cputype(type);
cpu = NULL, type = NULL;
if (is_processor_line(buf)) {
/* s390-like "processor <n>:" per line */
- cpuinfo_parse_processor_line(&cpu, p);
+ cpuinfo_parse_processor_line(cxt, &cpu, p);
if (cpu) {
- lscpu_add_cpu(cxt, cpu, type);
- lscpu_unref_cpu(cpu);
+ lscpu_cpu_set_type(cpu, type);
cpu = NULL;
}
} else
- cpuinfo_parse_line(&type, &cpu, p);
+ cpuinfo_parse_line(cxt, &type, &cpu, p);
}
} while (1);
- lscpu_unref_cpu(cpu);
lscpu_unref_cputype(type);
fclose(fp);
- DBG(GATHER, ul_debug("cpuinfo done: CPUs: %zu, types: %zu",
- cxt->ncpus, cxt->ncputypes));
return 0;
}
maxn = cxt->maxcpus;
setsize = CPU_ALLOC_SIZE(maxn);
+ /* create CPUs from possible mask */
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;
- }
+ lscpu_create_cpus(cxt, cpuset, setsize);
cpuset_free(cpuset);
cpuset = NULL;
} else
ul_unref_path(cxt->procfs);
DBG(MISC, ul_debugobj(cxt, " freeing cpus"));
- for (i = 0; i < cxt->ncpus; i++)
+ for (i = 0; i < cxt->npossibles; 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->idx2cpunum);
free(cxt->present);
free(cxt->online);
free(cxt->cputypes);
}
lscpu_init_debug();
+
context_init_paths(cxt);
+ lscpu_read_cpulists(cxt);
lscpu_read_cpuinfo(cxt);
cxt->arch = lscpu_read_architecture(cxt);
- lscpu_read_cpulists(cxt);
lscpu_read_archext(cxt);
lscpu_read_vulnerabilities(cxt);
lscpu_read_numas(cxt);
sys = cxt->syscpu; /* /sys/devices/system/cpu/ */
setsize = CPU_ALLOC_SIZE(cxt->maxcpus); /* CPU set size */
- npos = cxt->ncpuspos; /* possible CPUs */
+ npos = cxt->npossibles; /* possible CPUs */
DBG(TYPE, ul_debugobj(ct, "reading %s/%s/%s topology",
ct->vendor ?: "", ct->model ?: "", ct->modelname ?:""));
- for (i = 0; i < cxt->ncpus; i++) {
+ for (i = 0; i < npos; i++) {
struct lscpu_cpu *cpu = cxt->cpus[i];
cpu_set_t *thread_siblings = NULL, *core_siblings = NULL;
cpu_set_t *book_siblings = NULL, *drawer_siblings = NULL;
int num, n;
- if (cpu->type != ct)
+ if (!cpu || cpu->type != ct)
continue;
num = cpu->logical_id;
if (!sw_topo) {
ct->ndrawers_per_system = ct->nbooks_per_drawer =
ct->nsockets_per_book = ct->ncores_per_socket = 0;
- if (!ct->ncores_per_socket)
+ if (!ct->ncores_per_socket && ct->nsockets)
ct->ncores_per_socket = ct->ncores / ct->nsockets;
if (!ct->nsockets_per_book && ct->nbooks)
ct->nsockets_per_book = ct->nsockets / ct->nbooks;
struct path_cxt *sys = cxt->syscpu;
size_t i;
- for (i = 0; i < cxt->ncpus; i++) {
+ for (i = 0; i < cxt->npossibles; i++) {
struct lscpu_cpu *cpu = cxt->cpus[i];
- int num = cpu->logical_id;
+ int num;
- DBG(TYPE, ul_debugobj(cpu, "#%d reading IDs", num));
+ if (!cpu)
+ continue;
+
+ num= cpu->logical_id;
+ DBG(CPU, ul_debugobj(cpu, "#%d reading IDs", num));
if (ul_path_readf_s32(sys, &cpu->coreid, "cpu%d/topology/core_id", num) != 0)
cpu->coreid = -1;
struct path_cxt *sys = cxt->syscpu;
size_t i;
- for (i = 0; i < cxt->ncpus; i++) {
+ for (i = 0; i < cxt->npossibles; i++) {
struct lscpu_cpu *cpu = cxt->cpus[i];
- int num = cpu->logical_id;
+ int num;
char mode[64];
- if (!cpu->type || cpu->type->dispatching < 0)
+ if (!cpu || !cpu->type || cpu->type->dispatching < 0)
continue;
+
+ num = cpu->logical_id;
if (ul_path_accessf(sys, F_OK, "cpu%d/polarization", num) != 0)
continue;