以前的博文
https://blog.csdn.net/leesagacious/article/details/107734812?spm=1001.2014.3001.5501
cpu从offline到online 是一个循序渐进的过程,崎岖坎坷, 包含了时钟、软中断、cpufreq … 多个模块的处理, 就像一个人跨越社会阶层一样. 不是一蹴而就的.
ok, 如果你偏要杠精说: 女生嫁人实现跃迁是一蹴而就, 那其实是生育议价权的原因, 一个学生高考从村庄到城市的逆袭是多年学习的结果, ‘更有极端的通过买彩票来实现一夜暴富, 不知道交了多少智商税. 中奖的概率比被雷劈还小, 😄, 去买吧,买个梦想,买个痴心妄想 .
先来看一个cpu_hp 状态跌落实验. 这是从最高能级cpu_active落到cpu_offline状态.
如果你没有明白, 下面帮你简单理解:
所谓的跃迁或跌落指的是从一个状态转变到另一个状态的过程.
ok, 是不是有点像波尔原子能级跃迁模型了 ? 😄,
不过这里从高能级跌落到低能级对外"释放"的是移动设备续航最重要的 电.
注意了, 原子核没有动,即cpu还是处于EL1状态(或EL2、EL3), 或ring0状态(X86).
不废话了, 看下面的小实验吧.
/*
* 该函数在系统启动前期被bootstrap cpu 执行.
* bp 是嫡出, AP是庶出. smp环境中也是嫡长子继承制啊, 其他的cpu就等着bp发出IPI吧.
* 欲戴王冠,必承其重, 解压内核、系统初始化等任务AP义不容辞,BP们则干瞪眼.😄
*/
void __init smp_init(void)
{
/*
* static DEFINE_PER_CPU(struct task_struct *, idle_threads);
*
* 为每个AP创建一个idle进程. idle_threads它是一个 PER CPU 类型.
* PER CPU 变量唯一的缺点是 被访问时 要禁止抢占. 空间换效率不说, 除此之外, 它很让人满意.
* 这是linux kernel 一个精彩的特性 !
*
* ok, 为什么要为AP们创建 idle thread ?
* 如果cpu 运行队列中没有可以运行的进程了, 那需要向其他cpu做均衡, 如果大家都很闲, 直接执行idle thread了
*/
idle_threads_init();
/*
* 核心来了!
* cpu hp thread. 它是一个内核线程.
* 执行 kthread_create_on_cpu()来实现, 在指定的cpu上创建 kthread, 且处于park状态.
* 这是cpu亲和性的一个应用场景. 但是这里作者考虑的却不是想着利用cpu缓存这个优势.
* 这里不允许cpuhp kthread 自由恋爱.就直接相亲一个cpu从一而终了 😄😄
*
* 现在过年回家, 发现绝大多数都是相亲的, 的确相亲比自由恋爱更能容易结婚.
* 不管婚后相处咋样, 男多女少大环境下,娶个wife急迫的人太多了.
* 三观啥的抛一边, 一年以后抱baby! ok, 完成人生一大任务.
*/
cpuhp_threads_init(void);
/*
* 啥也不说了, 看内核做服务做的真周到, 直接告诉你, 要喊醒AP让他们起来干活了.
*/
pr_info("Bringing up secondary CPUs ...\n");
/*
* 该函数实现的很是利索. 直接执行 cpu_up(), 把AP们跃迁到 CPU_ONLINE状态.
* 到了这里已经很明显了, 启动阶段的 Linux kernel 是风格干脆、不瞻前顾后的, BP以后直接就是AP了,
*
* ok, 从 uboot 作为火箭牺牲自己把 kernel img 这颗卫星送到轨道到现在所有的cpu都处于online state,
* 不容易呀, 就像韦伯红外望远镜一样,怎么wake up自身的探测设备、调整增益天线的幅度等等. 到这里阶段性任务已经全部结束了
*
* 一言以蔽之, uboot做的了初一, kernel就做的了十五 !
* 这是kerenl init 线程的功劳 !
*
* 接下来就是所有内核进程的鼻主,杰出的kthreadd 进程要诞生了 ! 😄
* 一旦kthreadd产生, 整个启动就完成了. 韦伯望远镜就开始工作模式了.
*/
bringup_nonboot_cpus(setup_max_cpus);
}
/*
* 目标很明确, 就是让该cpu的热插拔状态逾跃迁到 target状态.
* 路很遥远. 每一个状态都是一个坎, 都是一个目标, 都是cpu提升服务能力的一次升级.
* 当然了,终极目标就是 CPU_ONLINE, 坎坷比玄奘大师的九九八十一难还要多.
*/
static int cpu_up(unsigned int cpu, enum cpuhp_state target)
{
/*
* 这是 kernel的一个惯用伎俩, 上来啥也不说, 先考虑返回值.
* 有错误该函数自己处理不了就往外抛给caller, 没错误就继续执行下去.
*/
int err = 0;
/*
* cat /sys/devices/system/cpu/possible
*/
if (!cpu_possible(cpu)) {
pr_err("can't online cpu %d because it is not configured as may-hotadd at boot time\n", cpu);
#if defined(CONFIG_IA64)
pr_err("please check additional_cpus= boot parameter\n");
#endif
return -EINVAL;
}
out:
return err;
}