cpu topology
来源:互联网 发布:水平垂直奇偶校验算法 编辑:程序博客网 时间:2024/06/05 04:33
cpu的拓扑结构的定义如下:
struct cpu_topology {
int thread_id;
int core_id;
int cluster_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
};
可以看到cpu 拓扑结构相关的就是cluster/core/thread. 平时我们用lscpu看到就是这三个.
lscpu
Architecture: aarch64
Byte Order: Little Endian
CPU(s): 64
On-line CPU(s) list: 0-63
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 16
NUMA node(s): 4
NUMA node0 CPU(s): 0-15
NUMA node1 CPU(s): 16-31
NUMA node2 CPU(s): 32-47
NUMA node3 CPU(s): 48-63
kernel_init_freeable->smp_prepare_cpus->init_cpu_topology 来从dts表中parse cluster/core/thread的值填到cpu_topology 结构体中
void __init init_cpu_topology(void)
{
reset_cpu_topology();
/*
* Discard anything that was parsed if we hit an error so we
* don't use partial information.
*/
if (of_have_populated_dt() && parse_dt_topology())
reset_cpu_topology();
}
init_cpu_topology 首先调用将cpu_topology 结构体清零
static void __init reset_cpu_topology(void)
{
unsigned int cpu;
for_each_possible_cpu(cpu) {
struct cpu_topology *cpu_topo = &cpu_topology[cpu];
cpu_topo->thread_id = -1;
cpu_topo->core_id = 0;
cpu_topo->cluster_id = -1;
cpumask_clear(&cpu_topo->core_sibling);
cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
cpumask_clear(&cpu_topo->thread_sibling);
cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
}
}
然后调用of_have_populated_dt()判断当前是否有dts.判断的方法如下:
static inline bool of_have_populated_dt(void)
{
return of_root != NULL;
}
从这个判断也可以看到当前4.9的kernel中的cpu topology 不支持ACPI传递.
of_have_populated_dt()判断通过后就通过parse_dt_topology 来parse cluster/core/thread的值填到cpu_topology 结构体中。如果失败则调用reset_cpu_topology来清零
static int __init parse_dt_topology(void)
{
struct device_node *cn, *map;
int ret = 0;
int cpu;
cn = of_find_node_by_path("/cpus");
if (!cn) {
pr_err("No CPU information found in DT\n");
return 0;
}
/*
* When topology is provided cpu-map is essentially a root
* cluster with restricted subnodes.
*/
map = of_get_child_by_name(cn, "cpu-map");
if (!map)
goto out;
ret = parse_cluster(map, 0);
if (ret != 0)
goto out_map;
/*
* Check that all cores are in the topology; the SMP code will
* only mark cores described in the DT as possible.
*/
for_each_possible_cpu(cpu)
if (cpu_topology[cpu].cluster_id == -1)
ret = -EINVAL;
out_map:
of_node_put(map);
out:
of_node_put(cn);
return ret;
}
这个函数首先判断是否有/cpu这个节点,然后从cpu节点中找到cpu-map 这个子节点
然后调用parse_cluster来parse cluster
parse_cluster 先parse cluser再parse core
static int __init parse_core(struct device_node *core, int cluster_id,
int core_id)
{
char name[10];
bool leaf = true;
int i = 0;
int cpu;
struct device_node *t;
do {
snprintf(name, sizeof(name), "thread%d", i);
t = of_get_child_by_name(core, name);
if (t) {
leaf = false;
cpu = get_cpu_for_node(t);
if (cpu >= 0) {
cpu_topology[cpu].cluster_id = cluster_id;
cpu_topology[cpu].core_id = core_id;
cpu_topology[cpu].thread_id = i;
} else {
pr_err("%s: Can't get CPU for thread\n",
t->full_name);
of_node_put(t);
return -EINVAL;
}
of_node_put(t);
}
i++;
} while (t);
cpu = get_cpu_for_node(core);
if (cpu >= 0) {
if (!leaf) {
pr_err("%s: Core has both threads and CPU\n",
core->full_name);
return -EINVAL;
}
cpu_topology[cpu].cluster_id = cluster_id;
cpu_topology[cpu].core_id = core_id;
} else if (leaf) {
pr_err("%s: Can't get CPU for leaf core\n", core->full_name);
return -EINVAL;
}
return 0;
}
最终在parse_core 函数中将dts中的到的信息填到cpu_topology 这个结构体中。
struct cpu_topology {
int thread_id;
int core_id;
int cluster_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
};
可以看到cpu 拓扑结构相关的就是cluster/core/thread. 平时我们用lscpu看到就是这三个.
lscpu
Architecture: aarch64
Byte Order: Little Endian
CPU(s): 64
On-line CPU(s) list: 0-63
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 16
NUMA node(s): 4
NUMA node0 CPU(s): 0-15
NUMA node1 CPU(s): 16-31
NUMA node2 CPU(s): 32-47
NUMA node3 CPU(s): 48-63
kernel_init_freeable->smp_prepare_cpus->init_cpu_topology 来从dts表中parse cluster/core/thread的值填到cpu_topology 结构体中
void __init init_cpu_topology(void)
{
reset_cpu_topology();
/*
* Discard anything that was parsed if we hit an error so we
* don't use partial information.
*/
if (of_have_populated_dt() && parse_dt_topology())
reset_cpu_topology();
}
init_cpu_topology 首先调用将cpu_topology 结构体清零
static void __init reset_cpu_topology(void)
{
unsigned int cpu;
for_each_possible_cpu(cpu) {
struct cpu_topology *cpu_topo = &cpu_topology[cpu];
cpu_topo->thread_id = -1;
cpu_topo->core_id = 0;
cpu_topo->cluster_id = -1;
cpumask_clear(&cpu_topo->core_sibling);
cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
cpumask_clear(&cpu_topo->thread_sibling);
cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
}
}
然后调用of_have_populated_dt()判断当前是否有dts.判断的方法如下:
static inline bool of_have_populated_dt(void)
{
return of_root != NULL;
}
从这个判断也可以看到当前4.9的kernel中的cpu topology 不支持ACPI传递.
of_have_populated_dt()判断通过后就通过parse_dt_topology 来parse cluster/core/thread的值填到cpu_topology 结构体中。如果失败则调用reset_cpu_topology来清零
static int __init parse_dt_topology(void)
{
struct device_node *cn, *map;
int ret = 0;
int cpu;
cn = of_find_node_by_path("/cpus");
if (!cn) {
pr_err("No CPU information found in DT\n");
return 0;
}
/*
* When topology is provided cpu-map is essentially a root
* cluster with restricted subnodes.
*/
map = of_get_child_by_name(cn, "cpu-map");
if (!map)
goto out;
ret = parse_cluster(map, 0);
if (ret != 0)
goto out_map;
/*
* Check that all cores are in the topology; the SMP code will
* only mark cores described in the DT as possible.
*/
for_each_possible_cpu(cpu)
if (cpu_topology[cpu].cluster_id == -1)
ret = -EINVAL;
out_map:
of_node_put(map);
out:
of_node_put(cn);
return ret;
}
这个函数首先判断是否有/cpu这个节点,然后从cpu节点中找到cpu-map 这个子节点
然后调用parse_cluster来parse cluster
parse_cluster 先parse cluser再parse core
static int __init parse_core(struct device_node *core, int cluster_id,
int core_id)
{
char name[10];
bool leaf = true;
int i = 0;
int cpu;
struct device_node *t;
do {
snprintf(name, sizeof(name), "thread%d", i);
t = of_get_child_by_name(core, name);
if (t) {
leaf = false;
cpu = get_cpu_for_node(t);
if (cpu >= 0) {
cpu_topology[cpu].cluster_id = cluster_id;
cpu_topology[cpu].core_id = core_id;
cpu_topology[cpu].thread_id = i;
} else {
pr_err("%s: Can't get CPU for thread\n",
t->full_name);
of_node_put(t);
return -EINVAL;
}
of_node_put(t);
}
i++;
} while (t);
cpu = get_cpu_for_node(core);
if (cpu >= 0) {
if (!leaf) {
pr_err("%s: Core has both threads and CPU\n",
core->full_name);
return -EINVAL;
}
cpu_topology[cpu].cluster_id = cluster_id;
cpu_topology[cpu].core_id = core_id;
} else if (leaf) {
pr_err("%s: Can't get CPU for leaf core\n", core->full_name);
return -EINVAL;
}
return 0;
}
最终在parse_core 函数中将dts中的到的信息填到cpu_topology 这个结构体中。
0 0
- cpu topology
- cpu topology
- CPU topology 几个概念
- 玩转CPU Topology
- 玩转CPU Topology
- 玩转cpu topology
- 玩转CPU Topology
- 玩转CPU Topology
- Linux CPU Topology
- cpu topology sys文件系统接口
- 解决 CPU topology doesn't match maximum vcpu count
- Linux CPU core的电源管理(2)_cpu topology
- Linux功耗管理(30)Linux CPU core的电源管理(2)_cpu topology
- [转载] 玩转CPU Topology(NUMA、SMP、Socket、physical Processor、Core、Logical Processor、Cache)
- numa topology
- Transaction Topology
- Quotient Topology
- 运行Topology
- 在Windows和Linux之间传送文件
- LabWindows/CVI之无驱摄像头使用--实例:远程监控(TCP)
- javascript中的==和===
- MVC3.0中直接在VS中浏览cshtml页面
- 小程序学习--1
- cpu topology
- SHA1 安全加密算法 (微信分享获取签名时使用)
- JDBC事务、JTA(Java Transaction API)事务、容器事务
- Linux命令基本格式及目录处理命令
- Glassfish部署cxfwebservice,axis调用报错的问题
- 读写分离
- Charles Petzold《Code》----2017.1.13 读12章
- (一)1.3Java程序运行机制及运行过程
- Git远程分支和refs文件详解