lscpu: calculate threads number from type specific values

Don't use global CPU masks (like "online" or "present") to
calculate type specific number of threads due systems with
mixed CPU types.

It's also necessary to check all thread_siblings maps to get the
highest number, because some threads (CPUs) may be disables, for
example old lscpu calculates number of threads from the cpu0 and
if you disable cpu0's sibling (cpu4):

	CPU(s):                          8
	On-line CPU(s) list:             0-7
	Thread(s) per core:              2        <---
	Core(s) per socket:              4
	Socket(s):                       1

 # chcpu --disable 4
 CPU 4 disabled

	CPU(s):                          8
	On-line CPU(s) list:             0-3,5-7
	Off-line CPU(s) list:            4
	Thread(s) per core:              1        <--- !
	Core(s) per socket:              4
	Socket(s):                       1

because 'thread_siblings' contains only one thread for cpu0:

 # cat /sys/devices/system/cpu/cpu{0,1,2,3,4,5,6,7}/topology/thread_siblings_list
 0
 1,5
 2,6
 3,7
 cat: /sys/devices/system/cpu/cpu4/topology/thread_siblings_list: No such file or directory
 1,5
 2,6
 3,7

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2020-07-16 10:51:14 +02:00
parent b8a319460d
commit fa6a21bf63
1 changed files with 12 additions and 35 deletions

View File

@ -217,6 +217,7 @@ static int cputype_read_topology(struct lscpu_cxt *cxt, struct lscpu_cputype *ct
{
size_t i, setsize, npos;
struct path_cxt *sys;
int nthreads = 0;
sys = cxt->syscpu; /* /sys/devices/system/cpu/ */
setsize = CPU_ALLOC_SIZE(cxt->maxcpus); /* CPU set size */
@ -226,7 +227,7 @@ static int cputype_read_topology(struct lscpu_cxt *cxt, struct lscpu_cputype *ct
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;
int num, n;
if (cpu->type != ct)
continue;
@ -248,6 +249,12 @@ static int cputype_read_topology(struct lscpu_cxt *cxt, struct lscpu_cputype *ct
ul_path_readf_cpuset(sys, &drawer_siblings, cxt->maxcpus,
"cpu%d/topology/drawer_siblings", num);
n = CPU_COUNT_S(setsize, thread_siblings);
if (!n)
n = 1;
if (n > nthreads)
nthreads = n;
/* Allocate arrays for topology maps.
*
* For each map we make sure that it can have up to ncpuspos
@ -274,42 +281,12 @@ static int cputype_read_topology(struct lscpu_cxt *cxt, struct lscpu_cputype *ct
if (drawer_siblings)
add_cpuset_to_array(ct->drawermaps, &ct->ndrawers, drawer_siblings, setsize);
/* calculate threads */
if (!ct->nthreads) {
int ndrawers, nbooks, nsockets, ncores, nthreads;
/* threads within one core */
nthreads = CPU_COUNT_S(setsize, thread_siblings);
if (!nthreads)
nthreads = 1;
/* cores within one socket */
ncores = CPU_COUNT_S(setsize, core_siblings) / nthreads;
if (!ncores)
ncores = 1;
/* number of sockets within one book. Because of odd /
* non-present cpu maps and to keep calculation easy we make
* sure that nsockets and nbooks is at least 1.
*/
nsockets = cxt->npresents / nthreads / ncores;
if (!nsockets)
nsockets = 1;
/* number of books */
nbooks = cxt->npresents / nthreads / ncores / nsockets;
if (!nbooks)
ct->nbooks = 1;
/* number of drawers */
ndrawers = cxt->npresents / nbooks / nthreads / ncores / nsockets;
if (!ndrawers)
ndrawers = 1;
ct->nthreads = ndrawers * nbooks * nsockets * ncores * nthreads;
}
}
ct->nthreads = (ct->ndrawers ?: 1) *
(ct->nbooks ?: 1) *
(ct->nsockets ?: 1) *
(ct->ncores ?: 1) * nthreads;
DBG(TYPE, ul_debugobj(ct, " nthreads: %d", ct->nthreads));
DBG(TYPE, ul_debugobj(ct, " ncores: %d", ct->ncores));