轉自: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的工作流程來介紹,而是着重對一些參數進行了分析以便後續工作中引用。