【cpuidle】cpuidle代码框架

cpuidle解决什么问题

在计算机系统中,CPU的功能就是不断地取指、译码、执行,那如果CPU没有程序要执行,CPU不需要执行计算任务,也不需要响应外部中断事件,CPU要怎么办?在Linux kernel中,这种CPU的无所事事的状态,被称作idle状态,而cpuidle framework,就是为了管理这种状态。

CPU在idle的时候可以利用一些芯片技术比如clock gating、retention,让core进入睡眠省电模式,省电是又电子设备绕不开的话题。

cpuidle基本流程

任务调度、idle进程(何时进入idle)

idle进程的存在,是为了解决“何时idle”的问题。
在init进程(系统的第一个进程)完成初始化任务之后,将其转变为idle进程,由于该进程的优先级是最低的,所以当idle进程被调度到时,则说明系统的其它进程不再运行了,也即CPU idle了。最终,由idle进程调用idle指令(这里为WFI),让CPU进入idle状态。

WFI、WFE(如何idle)

WFI/WFE用于解决“怎么idle”的问题。
一般情况下,ARM CPU idle时,可以使用WFI指令,把CPU置为Wait for interrupt状态。该状态下,至少会把ARM core的clock关闭,以节省功耗(和具体ARM core的实现有关,可参考“ARM WFI和WFE指令”)。

软件流程

在SMP系统中,CPU启动的过程是:

1)先启动主CPU,启动过程和传统的单核系统类似:stext-->start_kernel-->rest_init-->cpu_startup_entry
2)启动其它CPU,可以有多种方式,例如CPU hotplug等,启动过程为:secondary_startup-->__secondary_switched-->secondary_start_kernel-->cpu_startup_entry

上面的代码位于./arch/arm64/kernel/head.S、init/main.c等等,感兴趣的读者可以自行参考。最终都会殊途同归,运行至cpu_startup_entry接口,该接口位于kernel/sched/idle.c中,负责处理CPU idle的事情。

cpuidle框架

cpuide framework的意义是什么?
ARM CPU的设计越来越复杂,对省电的要求也越来越苛刻,因而很多CPU会从“退出时的延迟”和“idle状态下的功耗”两个方面考虑,设计多种idle级别。对延迟较敏感的场合,可以使用低延迟、高功耗的idle;对延迟不敏感的场合,可以使用高延迟、低功耗的idle。

而软件则需要根据应用场景,在恰当的时候,选择一个合适的idle状态。而选择的策略是什么,就不是那么简单了。这就是cpuidle framework的存在意义。

kernel schedule模块

位于kernel\sched\idle.c中,负责实现idle线程的通用入口(cpuidle entry)逻辑,包括idle模式的选择、idle的进入等等。

core层

cpuidle core的代码主要包括:cpuidle.c、driver.c、governor.c、sysfs.c。

cpuidle core负责实现cpuidle framework的整体框架,主要功能包括:

  1. 根据cpuidle的应用场景,抽象出cpuidle device、cpuidle driver、cpuidle governor三个实体;
  2. 以函数调用的形式,向上层sched模块提供接口;
  3. 以sysfs的形式,向用户空间提供接口;
  4. 向下层的cpuidle drivers模块,提供统一的driver注册和管理接口;
  5. 向下层的governors模块,提供统一的governor注册和管理接口。

governor层

前面讲过,很多CPU提供了多种idle级别,这些idle级别的主要区别是“idle时的功耗”和“退出时延迟”。cpuidle driver(机制)负责定义这些idle状态(每一个状态的功耗和延迟分别是多少),并实现进入和退出相关的操作。最终,cpuidle driver会把这些信息告诉governor,由governor根据具体的应用场景,决定要选用哪种idle状态(策略)。

kernel中,cpuidle governor都位于governors/目录下。

driver层

负责idle机制的实现,即:如何进入idle状态,什么条件下会退出,等等。

不同的architecture、不同的CPU core,会有不同的cpuidle driver,平台驱动的开发者,可以在cpuidle core提供的框架之下,开发自己的cpuidle driver。代码主要包括:cpuidle-xxx.c。

cpuidle参考

cpuidle宏配置

cpuidle的宏配置比较简单,框架层和sysfs都默认编译了,只需要配置对应的驱动宏。

cpuidle调测命令

#ls /sys/devices/system/cpu/cpuidle/cpuX/cpuidle/stateY
  name,名称;
  desc,较为详细的描述;
  disable,cpuidle使能状态的读取和设置;
  latency,退出该state所需的时间,单位为us;
  power,该state下的功耗,单位为mW;
  time,停留在改状态的总时间,单位为us
  usage,进入该状态的次数。
# 进出次数
cat /sys/devices/system/cpu/cpu<x>/cpuidle/state<y>/usage
# 总时间
cat /sys/devices/system/cpu/cpu<x>/cpuidle/state<y>/time
posted @ 2022-06-30 17:53  zephyr~  阅读(1705)  评论(0编辑  收藏  举报