1 // SPDX-License-Identifier: GPL-2.0
12 #define CORE_SIB_FMT \
13 "%s/devices/system/cpu/cpu%d/topology/core_siblings_list"
14 #define THRD_SIB_FMT \
15 "%s/devices/system/cpu/cpu%d/topology/thread_siblings_list"
16 #define NODE_ONLINE_FMT \
17 "%s/devices/system/node/online"
18 #define NODE_MEMINFO_FMT \
19 "%s/devices/system/node/node%d/meminfo"
20 #define NODE_CPULIST_FMT \
21 "%s/devices/system/node/node%d/cpulist"
23 static int build_cpu_topology(struct cpu_topology *tp, int cpu)
26 char filename[MAXPATHLEN];
33 scnprintf(filename, MAXPATHLEN, CORE_SIB_FMT,
34 sysfs__mountpoint(), cpu);
35 fp = fopen(filename, "r");
39 sret = getline(&buf, &len, fp);
44 p = strchr(buf, '\n');
48 for (i = 0; i < tp->core_sib; i++) {
49 if (!strcmp(buf, tp->core_siblings[i]))
52 if (i == tp->core_sib) {
53 tp->core_siblings[i] = buf;
61 scnprintf(filename, MAXPATHLEN, THRD_SIB_FMT,
62 sysfs__mountpoint(), cpu);
63 fp = fopen(filename, "r");
67 if (getline(&buf, &len, fp) <= 0)
70 p = strchr(buf, '\n');
74 for (i = 0; i < tp->thread_sib; i++) {
75 if (!strcmp(buf, tp->thread_siblings[i]))
78 if (i == tp->thread_sib) {
79 tp->thread_siblings[i] = buf;
91 void cpu_topology__delete(struct cpu_topology *tp)
98 for (i = 0 ; i < tp->core_sib; i++)
99 zfree(&tp->core_siblings[i]);
101 for (i = 0 ; i < tp->thread_sib; i++)
102 zfree(&tp->thread_siblings[i]);
107 struct cpu_topology *cpu_topology__new(void)
109 struct cpu_topology *tp = NULL;
117 ncpus = cpu__max_present_cpu();
119 /* build online CPU map */
120 map = cpu_map__new(NULL);
122 pr_debug("failed to get system cpumap\n");
126 nr = (u32)(ncpus & UINT_MAX);
128 sz = nr * sizeof(char *);
129 addr = calloc(1, sizeof(*tp) + 2 * sz);
135 tp->core_siblings = addr;
137 tp->thread_siblings = addr;
139 for (i = 0; i < nr; i++) {
140 if (!cpu_map__has(map, i))
143 ret = build_cpu_topology(tp, i);
151 cpu_topology__delete(tp);
157 static int load_numa_node(struct numa_topology_node *node, int nr)
159 char str[MAXPATHLEN];
161 char *buf = NULL, *p;
167 node->node = (u32) nr;
169 scnprintf(str, MAXPATHLEN, NODE_MEMINFO_FMT,
170 sysfs__mountpoint(), nr);
171 fp = fopen(str, "r");
175 while (getline(&buf, &len, fp) > 0) {
176 /* skip over invalid lines */
177 if (!strchr(buf, ':'))
179 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
181 if (!strcmp(field, "MemTotal:"))
182 node->mem_total = mem;
183 if (!strcmp(field, "MemFree:"))
184 node->mem_free = mem;
185 if (node->mem_total && node->mem_free)
192 scnprintf(str, MAXPATHLEN, NODE_CPULIST_FMT,
193 sysfs__mountpoint(), nr);
195 fp = fopen(str, "r");
199 if (getline(&buf, &len, fp) <= 0)
202 p = strchr(buf, '\n');
217 struct numa_topology *numa_topology__new(void)
219 struct cpu_map *node_map = NULL;
220 struct numa_topology *tp = NULL;
221 char path[MAXPATHLEN];
228 scnprintf(path, MAXPATHLEN, NODE_ONLINE_FMT,
229 sysfs__mountpoint());
231 fp = fopen(path, "r");
235 if (getline(&buf, &len, fp) <= 0)
238 c = strchr(buf, '\n');
242 node_map = cpu_map__new(buf);
246 nr = (u32) node_map->nr;
248 tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0])*nr);
254 for (i = 0; i < nr; i++) {
255 if (load_numa_node(&tp->nodes[i], node_map->map[i])) {
256 numa_topology__delete(tp);
265 cpu_map__put(node_map);
269 void numa_topology__delete(struct numa_topology *tp)
273 for (i = 0; i < tp->nr; i++)
274 free(tp->nodes[i].cpus);