内核softlockup和hardlockup的一些参数分析【转】
转自:https://www.cnblogs.com/liuhailong0112/p/17619657.html
一 参数配置
Softlockup和hardlockup作为内核中的"lockup-看门狗"可以检查系统中调度和中断是否正常运转,其原理可以参考lockup-watchdogs。这两种watchdogs在/proc/sys/kernel/目录下有一些配置参数来对功能进行控制和调整
procfs下的接口文件名称 | 接口说明 | 内核中对应的变量 | 默认值 | 内核依赖配置 |
watchdog |
是否使能lockup watchdog, 是lockup检测的总开关 |
watchdog_user_enabled |
1; 内核启动参数控制: nowatchdog,0 |
CONFIG_LOCKUP_DETECTOR |
soft_watchdog |
是否使能softlockup检测 |
soft_watchdog_user_enabled |
1; 内核启动参数控制: nosoftlockup, 0
|
CONFIG_LOCKUP_DETECTOR |
nmi_watchdog |
是否使能hardlockup检测 |
nmi_watchdog_user_enabled |
NMI_WATCHDOG_DEFAULT (CONFIG_HARDLOCKUP_DETECTOR || CONFIG_HAVE_NMI_WATCHDOG 使能情况下值为1,否则为0);
内核启动参数控制: nmi_watchdog=0或者 nmi_watchdog=1 |
CONFIG_LOCKUP_DETECTOR |
watchdog_cpumask | 标记哪些cpu上线lockup watchdog | watchdog_cpumask | housekeeping_cpumask(HK_FLAG_TIMER); | CONFIG_LOCKUP_DETECTOR |
watchdog_thresh |
lockup检测的阈值的基础参数; softlockup和hardlockup的阈值通过 这个参数计算得到。 |
watchdog_thresh |
10 内核启动参数控制: watchdog_thresh=xx |
CONFIG_LOCKUP_DETECTOR |
softlockup_panic |
发生softlockup事件时是否触发 系统panic |
softlockup_panic | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE | CONFIG_SOFTLOCKUP_DETECTOR |
softlockup_all_cpu_backtrace | 发生softlockup事件时是否打印各个
CPU的backtrace |
sysctl_softlockup_all_cpu_backtrace | 0 |
CONFIG_SOFTLOCKUP_DETECTOR && CONFIG_SMP |
hardlockup_panic | 发生hardlockup事件时是否触发
系统panic |
hardlockup_panic |
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE; 内核参数控制: nmi_watchdog=panic或者 nmi_watchdog=nopanic控制 |
CONFIG_HARDLOCKUP_DETECTOR |
hardlockup_all_cpu_backtrace | 发生hardlockup事件时是否打印各个
CPU的backtrace |
sysctl_hardlockup_all_cpu_backtrace | 0 |
CONFIG_HARDLOCKUP_DETECTOR && CONFIG_SMP |
二 检查周期
Lockup-watchdog是周期性采样来实施检查的。softlockup和hardlockup的采样源不一样,采样的周期也不一样,下面咱们来看看采样周期。
采样\名称 | softlockup | hardlockup |
采样方式 | hrtimer | PMU CYCLES |
采样周期 |
sample_period = watchdog_thresh*2/5 (秒) |
wd_attr->sample_period = watchdog_thresh(秒) |
参数说明 | watchdog_thresh默认为10 |
watchdog_thresh默认为10 |
2.1 softlockup检查周期
Softlockup的检查周期保存在一个全局变量sample_period中,这个变量在lockup-watchdog初始化时调用lockup_detector_reconfigure()函数时计算得到:
static int get_softlockup_thresh(void) { return watchdog_thresh * 2; } static void set_sample_period(void) { /* * convert watchdog_thresh from seconds to ns * the divide by 5 is to give hrtimer several chances (two * or three with the current relation between the soft * and hard thresholds) to increment before the * hardlockup detector generates a warning */ sample_period = get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); }
通过这部分计算代码可以看到sample_period=watchdog_thresh*2/5。
2.2 hardlockup检查周期
Hardlockup检查周期是在PMU event创建时候确定
static int hardlockup_detector_event_create(void) { struct perf_event_attr *wd_attr; //...... wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh); //...... } u64 hw_nmi_get_sample_period(int watchdog_thresh) { return (u64)(cpu_khz) * 1000 * watchdog_thresh; }
从这里看到hardlockup的perf event采样周期为 cpu_khz*1000 * watchdog_thresh。其中: cpu_khz是 CPU主频/1000,CPU主频即每秒cycle数。因此PMU cycles按此频率采样,就是watchdog_thresh秒。
三 门限
首先以表格方式来看看softlockup和hardlockup两种lockup-watchdog的门限:
lockup\相关说明 | 门限计算式 | 默认值 | 相关参数 |
softlockup | watchdog_thresh*2 | 20秒 | watchdog_thresh,与sysctl kernel.watchdog_thresh关联 |
hardlockup | watchdog_thresh * 4/5 | 8秒 | watchdog_thresh,与sysctl kernel.watchdog_thresh关联 |
3.1 softlockup门限
Softlockup门限是watchdog_thresh*2,其中watchdog_thresh可以通过/proc/sys/kernel/watchdog_thresh来配置。
static int get_softlockup_thresh(void) { return watchdog_thresh * 2; }
所以softlockup门限默认值是20秒。
3.2 hardlockup门限
Hardlockup的门限是watchdog_thresh * 4/5,默认情况下面hardlockup门限值就是8秒。
static int get_softlockup_thresh(void) { return watchdog_thresh * 2; //watchdog来自于/proc/sys/kernel/watchdog_thresh } static void set_sample_period(void) { sample_period = get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); watchdog_update_hrtimer_threshold(sample_period); } void watchdog_update_hrtimer_threshold(u64 period) { watchdog_hrtimer_sample_threshold = period * 2; }
四 保活周期
下面是softlockup和hardlockup"保活"周期的一个分析。
lockup\说明 | watchdog形式 | 周期 | 更新变量 |
softlockup | stop worker | sample_period | percpu(watchdog_touch_ts) |
hardlockup | hrtimer | sample_period | percpu(hrtimer_interrupts) |
4.1 softlockup保活
Softlockup是以Linux中优先级最高的调度类中stop worker来进行保活;这个stop worker线程以sample_period为周期被hrtimer触发,sample_period也就是2.1中的softlockup检查周期:
stop_one_cpu_nowait(smp_processor_id(), softlockup_fn, NULL, this_cpu_ptr(&softlockup_stop_work))
这个stop worker被触发后会去更新 watchdog_touch_ts这个每CPU变量:__this_cpu_write(watchdog_touch_ts, get_timestamp())
4.2 hardlockup保活
Hardlockup会有一个sample_period为周期的hrtimer反复触发去更新hrtimer_interrupts这个每CPU变量: __this_cpu_inc(hrtimer_interrupts)
hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period))
此外,这个hrtimer也就是4.1中触发stop worker的hrtimer,没错,他们是复用的。
总结
本文以linux-5.10代码为背景进行分析。分析线条不是按照lockup-watchdog的工作流程来介绍,而是着重对一些参数进行了分析以便后续工作中引用。