如何在内核中启动secondary cpu

描述

启动secondary cpu

内核在启动secondary cpu之前当然需要为其准备好执行环境,因为内核中cpu最终都将由调度器管理,故此时调度子系统应该要初始化完成。

同时cpu启动完成转交给调度器之前,并没有实际的业务进程,而我们知道内核中cpu在空闲时会执行idle进程。因此,在其启动之前需要为每个cpu初始化一个idle进程。

另外,由于将一个cpu通过热插拔方式移除后,再次启动该cpu的流程,与secondary cpu的启动流程是相同的,因此内核复用了cpu hotplug框架用于启动secondary cpu。

而内核为每个cpu都分配了一个独立的hotplug线程,用于执行本cpu相关的热插拔流程。为此,内核通过以下流程执行secondary cpu启动操作:

SMP

idle进程初始化

以下代码为每个非boot cpu分配一个idle进程

void __init idle_threads_init(void)
{
	…
	boot_cpu = smp_processor_id();
	for_each_possible_cpu(cpu) {                 (1if (cpu != boot_cpu)
			idle_init(cpu);              (2)
	}
}

(1)遍历系统中所有的possible cpu

(2)若该cpu为secondary cpu,则为其初始化一个idle进程

hotplug线程初始化

以下代码为每个cpu初始化一个hotplug线程

void __init cpuhp_threads_init(void)
{
	BUG_ON(smpboot_register_percpu_thread(&cpuhp_threads));
	kthread_unpark(this_cpu_read(cpuhp_state.thread));
}

其中线程的描述结构体定义如下:

static struct smp_hotplug_thread cpuhp_threads = {
	.store			= &cpuhp_state.thread,               (1)
	.create			= &cpuhp_create,                     (2)
	.thread_should_run	= cpuhp_should_run,                  (3)
	.thread_fn		= cpuhp_thread_fun,                  (4)
	.thread_comm		= "cpuhp/%u",                        (5)
	.selfparking		= true,                              (6)
}

(1)用于保存cpu上的task struct指针

(2)线程创建时调用的回调

(3)该回调用于获取线程是否需要退出标志

(4)cpu hotplug主函数,执行实际的hotplug操作

(5)该线程的线程名

(6)用于设置线程创建完成后,是否将其设置为park状态

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分