CPU在没有任务可运行时,会进入到休眠状态,以下参数可以控制cpu的休眠状态。
- processor.max_cstate,其值为0-9,数值越大,表示CPU休眠的程度越深。
- intel_idle.max_cstate,设置intel_idle驱动允许使用的最大C-state深度。0表示禁用intel_idle.
- intel_pstate=disable,禁用Intel CPU专用的频率调节驱动
- idle=poll/halt/momwait
poll:禁止CPU进入休眠状态
halt:使用HALT指令让CPU最多进入到C1休眠状态。
nomwait:进入休眠状态时,禁止使用MWAIT指令。 - nohz,CPU处于idle状态时,暂停tickless。
- nohz_full,当CPU对应的runqueue只有一个任务或者运行实时进程时,停掉tickless.
下面介绍一下idle进程。
idle化身自Linux的0号进程,是所有进程的祖先。0号进程由静态结构体 struct task_struct init_task创建,然后它创建首个内核线程kernel_init。除此之外,通过call cpu_startup_entry这个函数(实际执行到do_idle()),来实现不同程度的躺平。不同generation,不同架构的CPU实现的idle也是不一样的。
X86结构
HLT
只能在ring0的特权级执行,CPU进入C1,但是APIC/BUS/CACHE正常工作,当中断发生时,转到执行状态。
PAUSE
使CPU进入休眠状态(30 cycles),是为了降低CPU在spin-lock下的资源消耗。当spinlock尝试获得锁失败的时候,会进行busy loop,不断检测锁的状态,
MWAIT/MONITOR
同样运行在ring0级别,调用MONITOR地址范围,然后是MWAIT进入休眠,一旦监控的地址内容被修改,则唤醒CPU,唤醒条件包括中断和cacheline invalidate。MWAIT也可使CPU进入不同的Cstate,最大到C6,完全停止CPU。
UMWAIT/UMONITOR
允许在用户态进入休眠状态,只不过休眠深度很有限。
TPAUSE
附带了一个timer,让CPU在规定的时间内休眠。
ARM
YIELD
类似于X86的PAUSE