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
);