mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
145 lines
2.4 KiB
C
145 lines
2.4 KiB
C
|
// SPDX-License-Identifier: GPL-2.0
|
||
|
#include <sys/param.h>
|
||
|
|
||
|
#include "cputopo.h"
|
||
|
#include "cpumap.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
|
||
|
#define CORE_SIB_FMT \
|
||
|
"/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
|
||
|
#define THRD_SIB_FMT \
|
||
|
"/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
|
||
|
|
||
|
static int build_cpu_topology(struct cpu_topology *tp, int cpu)
|
||
|
{
|
||
|
FILE *fp;
|
||
|
char filename[MAXPATHLEN];
|
||
|
char *buf = NULL, *p;
|
||
|
size_t len = 0;
|
||
|
ssize_t sret;
|
||
|
u32 i = 0;
|
||
|
int ret = -1;
|
||
|
|
||
|
sprintf(filename, CORE_SIB_FMT, cpu);
|
||
|
fp = fopen(filename, "r");
|
||
|
if (!fp)
|
||
|
goto try_threads;
|
||
|
|
||
|
sret = getline(&buf, &len, fp);
|
||
|
fclose(fp);
|
||
|
if (sret <= 0)
|
||
|
goto try_threads;
|
||
|
|
||
|
p = strchr(buf, '\n');
|
||
|
if (p)
|
||
|
*p = '\0';
|
||
|
|
||
|
for (i = 0; i < tp->core_sib; i++) {
|
||
|
if (!strcmp(buf, tp->core_siblings[i]))
|
||
|
break;
|
||
|
}
|
||
|
if (i == tp->core_sib) {
|
||
|
tp->core_siblings[i] = buf;
|
||
|
tp->core_sib++;
|
||
|
buf = NULL;
|
||
|
len = 0;
|
||
|
}
|
||
|
ret = 0;
|
||
|
|
||
|
try_threads:
|
||
|
sprintf(filename, THRD_SIB_FMT, cpu);
|
||
|
fp = fopen(filename, "r");
|
||
|
if (!fp)
|
||
|
goto done;
|
||
|
|
||
|
if (getline(&buf, &len, fp) <= 0)
|
||
|
goto done;
|
||
|
|
||
|
p = strchr(buf, '\n');
|
||
|
if (p)
|
||
|
*p = '\0';
|
||
|
|
||
|
for (i = 0; i < tp->thread_sib; i++) {
|
||
|
if (!strcmp(buf, tp->thread_siblings[i]))
|
||
|
break;
|
||
|
}
|
||
|
if (i == tp->thread_sib) {
|
||
|
tp->thread_siblings[i] = buf;
|
||
|
tp->thread_sib++;
|
||
|
buf = NULL;
|
||
|
}
|
||
|
ret = 0;
|
||
|
done:
|
||
|
if (fp)
|
||
|
fclose(fp);
|
||
|
free(buf);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void cpu_topology__delete(struct cpu_topology *tp)
|
||
|
{
|
||
|
u32 i;
|
||
|
|
||
|
if (!tp)
|
||
|
return;
|
||
|
|
||
|
for (i = 0 ; i < tp->core_sib; i++)
|
||
|
zfree(&tp->core_siblings[i]);
|
||
|
|
||
|
for (i = 0 ; i < tp->thread_sib; i++)
|
||
|
zfree(&tp->thread_siblings[i]);
|
||
|
|
||
|
free(tp);
|
||
|
}
|
||
|
|
||
|
struct cpu_topology *cpu_topology__new(void)
|
||
|
{
|
||
|
struct cpu_topology *tp = NULL;
|
||
|
void *addr;
|
||
|
u32 nr, i;
|
||
|
size_t sz;
|
||
|
long ncpus;
|
||
|
int ret = -1;
|
||
|
struct cpu_map *map;
|
||
|
|
||
|
ncpus = cpu__max_present_cpu();
|
||
|
|
||
|
/* build online CPU map */
|
||
|
map = cpu_map__new(NULL);
|
||
|
if (map == NULL) {
|
||
|
pr_debug("failed to get system cpumap\n");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
nr = (u32)(ncpus & UINT_MAX);
|
||
|
|
||
|
sz = nr * sizeof(char *);
|
||
|
addr = calloc(1, sizeof(*tp) + 2 * sz);
|
||
|
if (!addr)
|
||
|
goto out_free;
|
||
|
|
||
|
tp = addr;
|
||
|
addr += sizeof(*tp);
|
||
|
tp->core_siblings = addr;
|
||
|
addr += sz;
|
||
|
tp->thread_siblings = addr;
|
||
|
|
||
|
for (i = 0; i < nr; i++) {
|
||
|
if (!cpu_map__has(map, i))
|
||
|
continue;
|
||
|
|
||
|
ret = build_cpu_topology(tp, i);
|
||
|
if (ret < 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
out_free:
|
||
|
cpu_map__put(map);
|
||
|
if (ret) {
|
||
|
cpu_topology__delete(tp);
|
||
|
tp = NULL;
|
||
|
}
|
||
|
return tp;
|
||
|
}
|