util/cpu: add big.LITTLE cpu detection

it's useful for drivers to be able to detect big.LITTLE topology in
order to make decisions about how to handle workloads (specifically as
it relates to threading)

Reviewed-by: Rob Clark <robdclark@chromium.org>

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21926>
This commit is contained in:
Mike Blumenkrantz 2023-03-15 10:26:13 -04:00 committed by Marge Bot
parent 54d01db8a8
commit 0cc93a4603
2 changed files with 46 additions and 0 deletions

View file

@ -38,6 +38,7 @@
#include "util/u_debug.h"
#include "u_cpu_detect.h"
#include "u_math.h"
#include "os_file.h"
#include "c11/threads.h"
#include <stdio.h>
@ -478,6 +479,40 @@ get_cpu_topology(void)
memset(util_cpu_caps.cpu_to_L3, 0xff, sizeof(util_cpu_caps.cpu_to_L3));
#if DETECT_OS_LINUX
uint64_t big_cap = 0;
unsigned num_big_cpus = 0;
uint64_t *caps = malloc(sizeof(uint64_t) * util_cpu_caps.max_cpus);
bool fail = false;
for (unsigned i = 0; caps && i < util_cpu_caps.max_cpus; i++) {
char name[PATH_MAX];
snprintf(name, sizeof(name), "/sys/devices/system/cpu/cpu%u/cpu_capacity", i);
size_t size = 0;
char *cap = os_read_file(name, &size);
if (!cap) {
num_big_cpus = 0;
fail = true;
break;
}
errno = 0;
caps[i] = strtoull(cap, NULL, 10);
free(cap);
if (errno) {
fail = true;
break;
}
big_cap = MAX2(caps[i], big_cap);
}
if (!fail) {
for (unsigned i = 0; caps && i < util_cpu_caps.max_cpus; i++) {
if (caps[i] >= big_cap / 2)
num_big_cpus++;
}
}
free(caps);
util_cpu_caps.nr_big_cpus = num_big_cpus;
#endif
#if DETECT_ARCH_X86 || DETECT_ARCH_X86_64
/* AMD Zen */
if (util_cpu_caps.family >= CPU_AMD_ZEN1_ZEN2 &&

View file

@ -126,8 +126,19 @@ struct util_cpu_caps_t {
unsigned max_vector_bits;
uint16_t cpu_to_L3[UTIL_MAX_CPUS];
/* Affinity masks for each L3 cache. */
util_affinity_mask *L3_affinity_mask;
/**
* number of "big" CPUs in big.LITTLE configuration
*
* a "big" CPU is defined as anything with >= 50% the capacity of the largest CPU,
* useful for drivers determining how many and what kinds of threads to use
* example: 1x prime + 3x big + 4x little = 4x "big" cores
*
* A value of zero indicates that CPUs are homogeneous.
*/
int16_t nr_big_cpus;
};
struct _util_cpu_caps_state_t {